一、求某天是星期几
- 给定一个基准日期,知道基准日期是星期几(a),算的指定日期(y1,m1,d1)与基准日期(y2,m2,d2)间隔的天数(b)
- w = (a + b % 7),如果 w > 7,返回 w % 7,得到星期几
求(y,m,d)是星期几
1、先求 w = (a + b % 7)
2、给定基准日期,公元前1年12月31日为星期七,a = 0
3、求间隔天数,b
- [1,y - 1] 的整年数 加上 最后一年的部分天数求得间隔天数,b = (y - 1)* 365 + p * 1 + q,p = [1,y - 1]的闰年数,q = (m, d)是y年的第几天
- [(y - 1)* 365 ] 可以化简为(y - 1)
如:39 % 7 = 4,4 % 7 = 4,(4 + 5 * 35)% 7 = 4 % 7,(某个数 + 7的倍数)% 7 = 某个数 % 7, [ (y - 1) * 364 + (y - 1) + p + q ] % 7 = [(y - 1) + p + q ],因为 364(y - 1)是7的倍数
- 求p,[1,y - 1] 年间的闰年数
- 判断闰年的条件:(y % 4 == 0 && y % 100 != 0) || y % 400 == 0
- [1, y-1]有(y - 1)/4个数能被 4 整除,有(y - 1) /100个数能被 100 整除,有(y-1)/400个数能被400整除
- p = (y - 1)/4 + (y - 1)/100 + (y-1)/400
- 求q,(m, d) 是 y 年的第多少天
public static int diff(int y, int m, int d){
int[] months = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){
months[1] = 29;
}
int n = 0;
for (int i = 0; i < m - 1; i++) {
n += months[i];
}
n += d;
return n;
}
- 最终的公式为:b = (y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q
6、w = (7 + [(y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q] % 7)
5、判断 w 是否为需要 %7
public static int getWeek(int y, int m, int d){
int q = diff(y, m, d);
int week = (7 + ((y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q)% 7);
return week == 7 ? week : week % 7;
}
public static int diff(int y, int m, int d){
int[] months = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int n = 0;
for (int i = 0; i < m - 1; i++) {
n += months[i];
}
n += d;
if(m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)){
n++;
}
return n;
}
二、求美国节日
关于找到某月的第n个星期e,判断这天是几号
- 找到每月1号是星期几(w)
- 根据规律,1 + [ 7 + (e - w) ] % 7 + (n - 1) * 7,得到这天是几号
1、题目描述
2、代码解决
import java.util.Scanner;
public class Main {
// 判断某年某月某日 是星期几
public static int getWeek(int y, int m, int d){
int q = diff(y, m, d);
int week = (7 + ((y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q)% 7);
return week == 7 ? week : week % 7;
}
// 判断某年某月某日与 公元前1年12月31日 的间隔天数
public static int diff(int y, int m, int d){
int[] months = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int n = 0;
for (int i = 0; i < m - 1; i++) {
n += months[i];
}
n += d;
if(m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)){
n++;
}
return n;
}
// 判断某月的第n个星期e 是 几号
// w - 这个月1号是星期几
// n - 第几个
// e - 星期几
public static int getDay(int w, int n, int e){
return 1 + (7 + (e - w)) % 7 + (n - 1) * 7;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()){
int y = scanner.nextInt();
System.out.printf("%d-01-01\n", y);
int w = getWeek(y, 1, 1);
int d = getDay(w, 3, 1);
System.out.printf("%d-01-%02d\n", y, d);
w = getWeek(y, 2, 1);
d = getDay(w, 3, 1);
System.out.printf("%d-02-%02d\n", y, d);
// 5月的最后一个星期一
w = getWeek(y, 6, 1);
d = w == 1 ? 25 : 31 - (w - 2);
System.out.printf("%d-05-%02d\n", y, d);
System.out.printf("%d-07-04\n", y);
w = getWeek(y, 9, 1);
d = getDay(w, 1, 1);
System.out.printf("%d-09-%02d\n", y, d);
w = getWeek(y, 11, 1);
d = getDay(w, 4, 4);
System.out.printf("%d-11-%02d\n", y, d);
System.out.printf("%d-12-25\n", y);
}
}
}
三、求间隔天数
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
int y1 = scanner.nextInt();
int m1 = scanner.nextInt();
int d1 = scanner.nextInt();
int y2 = scanner.nextInt();
int m2 = scanner.nextInt();
int d2 = scanner.nextInt();
System.out.println(intervalDate(y1, m1, d1, y2, m2, d2));
}
}
public static int intervalDate(int y1, int m1, int d1, int y2, int m2, int d2){
int p1 = gradeDate(y1, m1, d1);
int p2 = gradeDate(y2, m2, d2);
int leapYear = leadYearSum(y1, y2 - 1);
return (y2 - y1) * 365 + leapYear + p2 - p1;
}
// 判断某年是否是闰年
public static boolean isLeapYear(int y){
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}
// 判断 [y1, y2] 年间闰年的天数
public static int leadYearSum(int y1, int y2){
int sum = 0;
for (int i = y1; i <= y2; i++) {
if(isLeapYear(i)){
sum++;
}
}
return sum;
}
// 判断 (y,m,d) 是 y 年的第几天
public static int gradeDate(int y, int m, int d){
int[] months = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sum = 0;
for (int i = 1; i <= m - 1; i++) {
sum += months[i];
}
if(m > 2 && isLeapYear(y)){
sum++;
}
sum += d;
return sum;
}
四、淘宝网店
1、题目描述
题目链接
2、丝路与代码
- 可以套用间隔天数的公式,将原来的每个月份的天数改成每月利润数{62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62}
- 需要注意的是,求(y1, m1, d1) ---- (y2, m2, d2) 的利润,包括(y1, m1, d1)、(y2, m2, d2),间隔天数的公式并不包括(y1,m1,d1)天,最后需要添加这一天的利润
- (y2 - y1)* 579 + [y1, y2-1]间的闰年数 * 1 + p2 - p1 + (y1, m1, d1)天的利润
(p表示从 [ (y2, 1,1), (y2, m2, d2) ] 间的利润)
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int y1 = scanner.nextInt();
int m1 = scanner.nextInt();
int d1 = scanner.nextInt();
int y2 = scanner.nextInt();
int m2 = scanner.nextInt();
int d2 = scanner.nextInt();
int[] profit = {
0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62};
int p1 = getPartProfit(y1, m1, d1, profit);
int p2 = getPartProfit(y2, m2, d2, profit);
int result = 579*(y2 - y1) + p2 - p1;
result += leadYearSum(y1, y2 - 1);
if(isPrimeMonth(m1)){
result += 2;
} else {
result += 1;
}
System.out.println(result);
}
// 得到当年的部分利润
public static int getPartProfit(int y, int m, int d, int[] profit){
int p = 0;
for (int i = 1; i <= m - 1; i++) {
p += profit[i];
}
if(m > 2 && isLeapYear(y)){
p += 1;
}
if(isPrimeMonth(m)){
p += d * 2;
} else {
p += d;
}
return p;
}
// 判断是否是素数月
public static boolean isPrimeMonth(int m){
return m == 2 || m == 3 || m == 5 || m == 7 || m == 11;
}
// 判断某年是否是闰年
public static boolean isLeapYear(int y){
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}
// 判断 [y1, y2] 年间闰年的天数
public static int leadYearSum(int y1, int y2){
int sum = 0;
for (int i = y1; i <= y2; i++) {
if(isLeapYear(i)){
sum++;
}
}
return sum;
}
阳光之城,海韵之都
山东日照
文章评论