目录
一、题目
二、思路
1、当两个年份不一样的时候
(1)from年剩余之后的收益
(2)中间年份的全部收益
(3)to年有的收益
2、同一个年份
三、代码
详细注释版本:
简化注释版本:
一、题目
淘宝网店 题目链接:淘宝网店
NowCoder在淘宝上开了一家网店。他发现在月份为素数的时候,当月每天能赚1元;否则每天能赚2元。现在给你一段时间区间,请你帮他计算总收益有多少。
输入描述:
输入包含多组数据。每组数据包含两个日期from和to (2000-01-01 ≤ from ≤ to ≤ 2999-12-31)。
日期用三个正整数表示,用空格隔开:year month day。
输出描述:
对应每一组数据,输出在给定的日期范围(包含开始和结束日期)内能赚多少钱。
输入
2000 1 1 2000 1 31
2000 2 1 2000 2 29
输出
62
29
二、思路
最主要的是计算两个日期之间的月份数以及判断素数的问题。
1、当两个年份不一样的时候
就有公式:
收益 = 2001年剩余之后的收益 + [2002,2021]全部收益 + 2022年有的收益
(1)from年剩余之后的收益
可以用 整年的收益 - 开始月日之前的收益。
因为每年就12个月,所以是素数的月份是固定的 :2、 3 、 5、 7、 11 。只有这5个月份是素数,每天挣一块钱。其他月份都是每天挣两块钱。
同时要注意闰年的问题:闰年的2月份会多一天,所以多挣两块钱。
(2)中间年份的全部收益
注意是闰年还是平年,计算整体收益。
(3)to年有的收益
to年有的收益,就是当前年月日之前的收益。
但是要判断月份是素数还是合数,进行运算。
最后整体相加即可。
2、同一个年份
在同一个年中,计算收益。
假设是 2001-4-5 到 2001-8-18 的收益。利用我们上面的方法函数进行计算。
三、代码
在实际写代码中还有很多地方是需要注意的(在代码注释中):
- 月份是否是素数判断;
- 闰年的处理;
- 计算from之前的收益时,要注意传入参数 fromDa - 1 ;
两个主要方法:
- yearSum(int y):计算整年的收益
- beforeSum(int y,int m,int d):计算指定日期在本年的收益。(月日之前的收益)
详细注释版本:
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:淘宝网店
* User: WangWZ
* Date: 2023-04-12
* Time: 19:13
*/
public class Main {
//判断是否是闰年
private static boolean isLeapYear(int y) {
return ((y % 400 == 0) || (y % 4 == 0 && y % 100 != 0));
}
//判断当前月数是否是素数
private static boolean isPrime(int m) {
if(m == 2 || m == 3 || m == 5 || m == 7 || m == 11) {
return true;
} else {
return false;
}
}
//整年全部的收益
private static int yearSum(int y) {
//2、3、5、7、11是素数月,所以每天只挣一块钱
//其他都是每天挣两块钱
//最后再判断是否是闰年,是闰年就+1(2月多挣一天)
int sum = 31 * 2 + 28 * 1 + 31 * 1 + 30 * 2 +
31 * 1 + 30 * 2 + 31 * 1 + 31 * 2 +
30 * 2 + 31 * 2 + 30 * 1 + 31 * 2;
if(isLeapYear(y)) {
sum += 1;
}
return sum;
}
//指定日期之前的收益
private static int beforeSum(int y,int m,int d) {
//要判断这个月是素数还是合数
//从当前月份向前累加
int sum = 0;
//1.先加当前月的没有过完整个月的天数的收益
if(isPrime(m)) {
sum += d * 1;
} else {
sum += d * 2;
}
//2.循环判断之前过完的月份是否是素数,并进行收益累加
//注意不能加当前月份,因为这个月还没过完
m--;
while(m > 0) {
switch(m){
case 1 :case 8: case 10: case 12:
sum += 31 * 2;
break;
case 2 :
sum += (isLeapYear(y)?29:28);
break;
case 3 :case 5: case 7:
sum += 31 * 1;
break;
case 4: case 6: case 9:
sum += 30 * 2;
break;
case 11:
sum += 30 * 1;
break;
}
m--;
}
return sum;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
int fromYear = scanner.nextInt();
int fromMo = scanner.nextInt();
int fromDa = scanner.nextInt();
int toYear = scanner.nextInt();
int toMo = scanner.nextInt();
int toDa = scanner.nextInt();
//总收益 = form剩余的收益 + 中间年份的收益 + to之前的收益
//from剩余的收益 = fromYear的全部收益 - from之前的收益
//这里注意:
//在算from之前的收益时,要 - 1。
//因为fromDa这一天是我们要计算收益的,因此不能减掉。
int n1 = yearSum(fromYear) - beforeSum(fromYear,fromMo,fromDa - 1);
//中间年份的收益:循环加中间年分的收益
int n2 = 0;
for(int i = fromYear+1; i < toYear; i++) {
n2 += yearSum(i);
}
//to之前的收益
int n3 = beforeSum(toYear,toMo,toDa);
//总收益sum
//这里因为不管什么情况都要加上n1和n3,所以可以直接定义sum时候就加上
//sum = n1 + n3;
int sum = 0;
if(fromYear == toYear) {
sum = n1 + n3 - yearSum(fromYear);
} else {
sum = n1 + n2 + n3;
}
System.out.println(sum);
}
}
}
简化注释版本:
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:淘宝网店
* User: WangWZ
* Date: 2023-04-12
* Time: 19:13
*/
public class Main {
//判断是否是闰年
private static boolean isLeapYear(int y) {
return ((y % 400 == 0) || (y % 4 == 0 && y % 100 != 0));
}
//判断当前月数是否是素数
private static boolean isPrime(int m) {
if(m == 2 || m == 3 || m == 5 || m == 7 || m == 11) {
return true;
} else {
return false;
}
}
//整年全部的收益
private static int yearSum(int y) {
int sum = 31 * 2 + 28 * 1 + 31 * 1 + 30 * 2 +
31 * 1 + 30 * 2 + 31 * 1 + 31 * 2 +
30 * 2 + 31 * 2 + 30 * 1 + 31 * 2;
if(isLeapYear(y)) {
sum += 1;
}
return sum;
}
//指定日期之前的收益
private static int beforeSum(int y,int m,int d) {
int sum = 0;
//1.先加当前月的没有过完整个月的天数的收益
if(isPrime(m)) {
sum += d * 1;
} else {
sum += d * 2;
}
//2.循环判断之前过完的月份是否是素数,并进行收益累加
m--;
while(m > 0) {
switch(m){
case 1 :case 8: case 10: case 12:
sum += 31 * 2;
break;
case 2 :
sum += (isLeapYear(y)?29:28);
break;
case 3 :case 5: case 7:
sum += 31 * 1;
break;
case 4: case 6: case 9:
sum += 30 * 2;
break;
case 11:
sum += 30 * 1;
break;
}
m--;
}
return sum;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
int fromYear = scanner.nextInt();
int fromMo = scanner.nextInt();
int fromDa = scanner.nextInt();
int toYear = scanner.nextInt();
int toMo = scanner.nextInt();
int toDa = scanner.nextInt();
//from剩余的收益 = fromYear的全部收益 - from之前的收益
int n1 = yearSum(fromYear) - beforeSum(fromYear,fromMo,fromDa - 1);
//中间年份的收益:循环加中间年分的收益
int n2 = 0;
for(int i = fromYear+1; i < toYear; i++) {
n2 += yearSum(i);
}
//to之前的收益
int n3 = beforeSum(toYear,toMo,toDa);
//总收益sum
int sum = 0;
if(fromYear == toYear) {
sum = n1 + n3 - yearSum(fromYear);
} else {
sum = n1 + n2 + n3;
}
System.out.println(sum);
}
}
}