intmain(){ int a, b, c; scanf("%d/%d/%d", &a, &b, &c); for(int date = 19600101; date < 20591231; date++){ int year = date / 10000, month = date % 10000 / 100, day = date % 100; if(check_valid(year, month, day)){ if(year % 100 == a && month == b && day == c || //年/月/日 month == a && day == b && year % 100 == c || //月/日/年 day == a && month == b && year % 100 == c){ //日/月/年 printf("%d-%02d-%02d\n",year, month, day); } } } return0; }
#include<iostream> #include<algorithm> usingnamespace std; //枚举year,先求对应位,再求出对应的回文数,如果满足日期条件,那么可以判断日期为回文数; int months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; boolcheck_valid(int date){ int year = date / 10000; int month = date % 10000 / 100;//先得到四位,再求前两位; int day = date % 100; //得到后两位; if(month >= 13 || !month || !day) returnfalse; if( month != 2 && day > months[month]) returnfalse; if(month == 2 ){ bool leap =( year % 4 == 0 && year % 100) || (year % 400 == 0);//是闰年; if( day > 28 + leap) returnfalse;//是闰年就加leap,否则不加; } returntrue; }
intmain(){ int date1, date2; cin >> date1 >> date2; int res = 0; for(int i = 0; i <= 10000; i++){ int date = i,x = i; while(x){ date = date * 10 + x %10; x /= 10; } if(check_valid(date) && date1 <= date && date <= date2) res ++; } cout << res ; return0; }
特别地:回文数求法与将数字转换为字符数组
1 2 3 4 5
int res; while(num){ res = res * 10 + num % 10; num /= 10; }//将数字123转换为回文数321;
1 2 3 4 5 6
int a[100], i = 0; int num = 123; while(num){ a[i] = num % 10; num /= 10; }
排序模拟
题目
sstream库处理数据读入问题
某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。
全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
输入格式
第一行包含整数 N,表示后面共有 N 行数据。
接下来 N 行,每行包含空格分开的若干个(不大于100个)正整数(不大于100000),每个整数代表一个ID号。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> typedeflonglong LL; usingnamespace std; constint N = 100010; int a[N],b[N],c[N]; int sa[N], sc[N]; int s[N]; int cnt[N];
intmain(){ int n; cin >> n; for(int i = 0; i < n; i++) scanf("%d", &a[i]), a[i]++;//加一防止越界 for(int i = 0; i < n; i++) scanf("%d", &b[i]), b[i]++; for(int i = 0; i < n; i++) scanf("%d", &c[i]), c[i]++; for(int i = 0; i < n; i++) cnt[a[i]]++; for(int i = 1; i < N; i++) s[i] = s[i - 1] + cnt[i]; for(int i = 0; i < n; i++) sa[i] = s[b[i] - 1];//减一为之前多加的; memset(cnt, 0, sizeof cnt);//重置为0; memset(s, 0, sizeof s); for(int i = 0; i < n; i++) cnt[c[i]]++; for(int i = 1; i < N; i++) s[i] = s[i - 1] + cnt[i]; for(int i = 0; i < n; i++) sc[i] = s[N - 1] - s[b[i]];//减一为之前多加的;计算大于b[i]个数 LL res = 0; for(int i = 0; i < n; i++) res += (LL)sa[i] * sc[i]; cout << res ; return0; }
题目-问题转换
小明这些天一直在思考这样一个奇怪而有趣的问题:
在 1∼N 的某个排列中有多少个连号区间呢?
这里所说的连号区间的定义是:
如果区间 [L,R][L,R] 里的所有元素(即此排列的第 L 个到第 R 个元素)递增排序后能得到一个长度为 R−L+1的“连续”数列,则称这个区间连号区间。
当 N 很小的时候,小明可以很快地算出答案,但是当 N 变大的时候,问题就不是那么简单了,现在小明需要你的帮助。