1、高斯日记
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
此题的易错点在于是否要算上高斯出生的那天,以及输出格式。
C++解法:
1 //从出生年开始算起,这种题一般都要掐头去尾,我直接把头加上了, 2 //出生第一天也算是活了一天,所以加119就行, 3 4 #include<iostream> 5 using namespace std; 6 int month[13] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 7 int main() 8 { 9 int n; 10 while (cin >> n) 11 { 12 n += 119; 13 int year = 1777; 14 while (n >= 365)//算出n所在的年份 15 { 16 if ((year % 4 == 0 && year % 400 != 0) || year % 400 == 0) 17 n -= 366; 18 else 19 n -= 365; 20 year++; 21 } 22 int mon; 23 if ((year % 4 == 0 && year % 400 != 0) || year % 400 == 0) 24 month[1]++;//如果是闰年2月天数加一 25 for (mon = 0; mon <= 11; mon++) 26 { 27 if (n > month[mon]) 28 n -= month[mon];//因为可以有4.30,所以这里是>不是>= 29 else 30 break; 31 } 32 33 printf("%d-%02d-%02d", year, mon+1, n); //注意输出格式 34 } 35 return 0; 36 }
Java解法:
1 import java.util.Calendar; 2 3 public class Demo { 4 5 public static void main(String[] args) { 6 Calendar c = Calendar.getInstance(); 7 //注意月份是从0开始算的,所以要设置为3月30日 8 c.set(1777, 3, 30); 9 c.add(Calendar.DAY_OF_MONTH, 8112); 10 11 //注意月份是从0开始算的,所以结果中的月份要+1 12 System.out.printf("%d-%02d-%02d ", c.get(Calendar.YEAR), 13 c.get(Calendar.MONTH) + 1, c.get(Calendar.DAY_OF_MONTH)); 14 } 15 16 }
因为1777年不在1999-9999年的可计算范围之内,所以可以退后两千年进行计算,此时需将结果减去2000年。
答案:1799-07-16
2、排他平方数
小明正看着 203879 这个数字发呆。
原来,203879 * 203879 = 41566646641
这有什么神奇呢?仔细观察,203879 是个6位数,并且它的每个数位上的数字都是不同的,并且它平方后的所有数位上都不出现组成它自身的数字。
具有这样特点的6位数还有一个,请你找出它!
再归纳一下筛选要求:
1. 6位正整数
2. 每个数位上的数字不同
3. 其平方数的每个数位不含原数字的任何组成数位
答案是一个6位的正整数。
解法一: 未优化,完全蛮力
1 #include<iostream> 2 #include<sstream> 3 4 using namespace std; 5 6 int main() 7 { 8 for (long long i = 100000; i <= 999999; ++i) 9 { 10 long long a = i * i; 11 int yi = i % 10; //个位 12 int er = (i % 100) / 10; //十位 13 if (er == yi) 14 continue; 15 int san = (i % 1000) / 100; //百位 16 if (san == yi || san == er) 17 continue; 18 int si = (i % 10000) / 1000; //千位 19 if (si == san || si == er || si == yi) 20 continue; 21 int wu = (i % 100000) / 10000; //万位 22 if (wu == si || wu == san || wu == er || wu == yi) 23 continue; 24 int liu = i / 100000; //十万位 25 if (liu == wu || liu == si || liu == san || liu == er || liu == yi) 26 continue; 27 char c1, c2, c3, c4, c5, c6; 28 c1 = char(yi + '0'); 29 c2 = char(er + '0'); 30 c3 = char(san + '0'); 31 c4 = char(si + '0'); 32 c5 = char(wu + '0'); 33 c6 = char(liu + '0'); 34 35 //int转为string 36 stringstream ss; 37 ss << a; 38 string s = ss.str(); 39 40 int flag = 0; 41 for (int j = 0; j < s.size(); ++j) 42 { 43 if (s[j] == c1 || s[j] == c2 || s[j] == c3 || s[j] == c4 || s[j] == c5 || s[j] == c6) 44 { 45 flag = 1; 46 break; 47 } 48 } 49 if(flag == 0) 50 cout << i << ": " << a << endl; 51 } 52 53 54 return 0; 55 }
解法二:(推荐掌握)
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 int vis[10]; //使用vis[j]保存i中数字j出现的次数 6 7 bool judge(long long int i) //判断i中是否有重复的数字 8 { 9 while (i) 10 { 11 if (vis[i % 10] == 0) //取i的最后一位数字,并保存其出现次数 12 vis[i % 10]++; 13 else //如果该数字已经出现过 14 return false; 15 i /= 10; //判断下一个数字 16 } 17 return true; 18 } 19 bool judge1(long long int i) //判断结果中是否包含i中的数字 20 { 21 while (i) 22 { 23 if (vis[i % 10] != 0) //该数字已经在i中出现过 24 return false; //返回错误 25 i /= 10; //判断下一个数字 26 } 27 return true; 28 } 29 int main() 30 { 31 long long int i; 32 for (i = 123456; i <= 987654; i++) //优化枚举范围 33 { 34 memset(vis, 0, sizeof(vis)); 35 if (!judge(i)) //判断i中是否有重复数字 36 continue; 37 if (!judge1(i*i)) //判断i的平方中是否包含i中的数字 38 continue; 39 cout << i << endl; 40 } 41 return 0; 42 }
答案:639172
3、振兴中华
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg)
从我做起振
我做起振兴
做起振兴中
起振兴中华
比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
注意:使用char数组保存字符串结果时,最后一定要补上' ',不然会产生错误结果!
1 #include<iostream> 2 #include<cstring> 3 4 using namespace std; 5 6 int vis[7][7]; //记录访问状态 7 int dx[4] = { 1,-1,0,0 }; 8 int dy[4] = { 0,0,1,-1 }; 9 char s[30]; //用字符数组保存路径上的值,一定要记住最后补上' ' 10 int result = 0; //保存总路线数 11 12 char mp[7][7] = { 13 "ABCDE", 14 "BCDEF", 15 "CDEFG", 16 "DEFGH" 17 }; 18 19 void dfs(int x, int y, int step) 20 { 21 s[step] = mp[x][y]; //用字符数组保存路径上的值 22 23 if (mp[x][y] == 'H') 24 { 25 s[step + 1] = '