日期推算
首先,我们要想找到一个月第N个星期W,一定需要一个参照物,最好的目标当然是这个月的第一天。拿到参照物后,我要能得 到参照物的星期数,然后就能得到结果了。所以这个题有两个难点:判断某个月的1号到底是周几,然后根据这个星期数得到这个月第N个星期W
方法:
1、三部曲求这一年过了几天
int DAYS[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool isLeapYear(int y) { return y % 400 == 0 || (y % 100 != 0 && y % 4 == 0); } int nDays(int y, int m, int d) { int n = d; for (int i = 0; i < m - 1; i++) { n += DAYS[i]; } if (m > 2 && isLeapYear(y)) { n++; } return n; }
2、 计算从基准日期,到带计算日期过了多少天,然后模取7得到星期几
优化防止爆int:
365*(y-1)%7==(365%7)*((y-1)%7)==1*(y-1)%7==(y-1)%7
int week(int y, int m, int d) { int tot=(y - 1) + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + nDays(y, m, d); //(y - 1)* 365+中间经历多少闰年*1+最后一年的天数 int w = tot % 7; if (w == 0) { w = 7; } return w; }
3、通过这个参照点拿到一个月的第N个星期W
那么,我们假设要拿到一个月的第一个周五,我们要怎么做呢?一个很简单的思路就是,先看看这个月的1号是周几,然后往后数就行了,假如1号是周四,那么2号就是第一个周五,假如1号是周六,那么7号就是第一个周五。
那么,怎么拿到这个向后的天数呢?我们发现,如果所求星期数比1号星期数大,那么直接相减后+1就是那一天了,例如1号周三,我要周五,那么(5-3)+1即可求出第一个周五是3号。那么反过来是所求星期数小,例如1号周三,我要周一,那么显然要先把周一看成周八才行。也就是(8-3)+1。第一个周一是6号。但是这样要判断,所以干脆统统都让它加7以后减,减完后的结果再mod一下7,就能得到结果了。也就是:(所求星期数 + 7 - 1号星期数) % 7 + 1。这样我们就拿到了求第一个周几公式。随后,我们只需要在这个公式上,加上7 * (n - 1),即刻求出第n个周几。
而面对某个月的最后一个周几,我们要做的是拿到下个月的第一天然后往回推即可。
// 已知当月1日是星期 w,计算第 n 个星期 e 是几号 int m1(int w, int n, int e) { return 1 + (n - 1) * 7 + (7 - w + e) % 7; }
#include <iostream> #include <cstdio> using namespace std; int DAYS[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool isLeapYear(int y) { return y % 400 == 0 || (y % 100 != 0 && y % 4 == 0); } // 求解 y,m,d 这一年过了多少天 int nDays(int y, int m, int d) { int n = d; for (int i = 0; i < m - 1; i++) { n += DAYS[i]; } if (m > 2 && isLeapYear(y)) { n++; } return n; } // 传入 y,m,d 计算从基准日期,到带计算日期过了多少天。 // 算出这个天数的 MOD 7 的同余数 int week(int y, int m, int d) { int tot=(y - 1) + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + nDays(y, m, d); int w = tot % 7; if (w == 0) { w = 7; } return w; } // 已知当月1日是星期 w,计算第 n 个星期 e 是几号 int m1(int w, int n, int e) { return 1 + (n - 1) * 7 + (7 - w + e) % 7; } int main() { int y; while (cin >> y) { printf("%d-01-01\n", y); int w; w = week(y, 1, 1); printf("%d-01-%02d\n", y, m1(w, 3, 1)); w = week(y, 2, 1); printf("%d-02-%02d\n", y, m1(w, 3, 1)); w = week(y, 6, 1); int d = (w == 1 ? 7 : w - 1); printf("%d-05-%02d\n", y, 32-d); printf("%d-07-04\n", y); w = week(y, 9, 1); printf("%d-09-%02d\n", y, m1(w, 1, 1)); w = week(y, 11, 1); printf("%d-11-%02d\n", y, m1(w, 4, 4)); printf("%d-12-25\n\n", y); } }
分解因数
16 16 = 2 * 2 * 2 * 2 345 345 = 3 * 5 * 23 44 44 = 2 * 2 * 11 90 90 = 2 * 3 * 3 * 5
对因子分解最简写法
#include<iostream> #include<cmath> using namespace std; int main() { int n; while(cin>>n) { printf("%d = ",n); for(int i=2;i<=sqrt(n);i++)//注意n是会改变的,所以遍历范围远小于n的算术平方根 { while(n!=i) { if(n%i==0) { printf("%d * ",i); n/=i; } else break; } } cout<<n<<endl; } return 0; }