历年题目
2012年
微生物繁殖
假设有两种微生物 X 和 Y
假设有两种微生物 X 和 Y
X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍)。
一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1个Y。
现在已知有新出生的 X=10, Y=89,求60分钟后Y的数目。
如果X=10,Y=90 呢?
本题的要求就是写出这两种初始条件下,60分钟后Y的数目。
题目的结果令你震惊吗?这不是简单的数字游戏!真实的生物圈有着同样脆弱的性质!也许因为你消灭的那只 Y 就是最终导致 Y 种群灭绝的最后一根稻草!
请忍住悲伤,把答案写在“解答.txt”中,不要写在这里!
请忍住悲伤,把答案写在“解答.txt”中,不要写在这里!
思路:我们可以先看一个新出生的X,在0.5、1.5、2.5……这些时刻会吃掉1个Y,在[0,1]、[1,2]、[2,3]……这些长度为1的区间内都会吃掉1个Y,那么我们不妨就都往前或往后挪0.5分钟,也就是直接算一个X每隔1分钟都会吃掉1个Y。因为半分钟不好处理,所以我们可以把时间整体上都乘2,那么就相当于每2分钟Y被吃掉X个,每6分钟X数目加倍,每4分钟Y数目加倍,还有一点就是当Y减少到小于等于0时就被吃完了。
答案:0 94371840
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 14 int main(){ 15 ios::sync_with_stdio(0); 16 int x,y; 17 cin>>x>>y; 18 for(int i=1;i<=120;i++){ 19 if(y<=0){ 20 y=0; 21 break; 22 }else{ 23 if(i%2==1) 24 y-=x; 25 if(i%4==0) 26 y=y*2; 27 if(i%6==0){ 28 x=2*x; 29 } 30 } 31 } 32 cout<<y<<endl; 33 return 0; 34 }
古堡算式
福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:
福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式:
ABCDE * ? = EDCBA
他对华生说:“ABCDE应该代表不同的数字,问号也代表某个数字!”
华生:“我猜也是!”
于是,两人沉默了好久,还是没有算出合适的结果来。
请你利用计算机的优势,找到破解的答案。
把 ABCDE 所代表的数字写出来。
答案写在“解答.txt”中,不要写在这里!
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 14 int main(){ 15 ios::sync_with_stdio(0); 16 for(int a=1;a<=9;a++){ 17 for(int b=0;b<=9;b++){ 18 if(b==a) 19 continue; //abcde代表不同数字 20 for(int c=0;c<=9;c++){ 21 if(c==a||c==b) 22 continue; 23 for(int d=0;d<=9;d++){ 24 if(d==a||d==b||d==c) 25 continue; 26 for(int e=1;e<=9;e++){ 27 if(e==a||e==b||e==c||e==d) 28 continue; 29 for(int f=2;f<=9;f++){ //edcba 反过来 30 if((a*10000+b*1000+c*100+d*10+e)*f==(e*10000+d*1000+c*100+b*10+a)) 31 cout<<a*10000+b*1000+c*100+d*10+e<<endl; 32 } 33 } 34 } 35 } 36 } 37 } 38 return 0; 39 }
海盗比酒量
有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复...... 直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。
等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
如果有多个可能的答案,请列出所有答案,每个答案占一行。
格式是:人数,人数,...
例如,有一种可能是:20,5,4,2,0
答案写在“解答.txt”中,不要写在这里!
--->枚举四轮的人数,1/a+1/b+1/c+1/d=1,变形一下就是bcd+acd+abd+abc=abcd。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 14 int main(){ 15 ios::sync_with_stdio(0); 16 for(int a=20;a>=1;a--){ 17 for(int b=a-1;b>=1;b--){ 18 for(int c=b-1;c>=1;c--){ 19 for(int d=c-1;d>=1;d--){ 20 if(b*c*d+a*c*d+a*b*d+a*b*c==a*b*c*d){ 21 cout<<a<<","<<b<<","<<c<<","<<d<<",0"<<endl; 22 } 23 } 24 } 25 } 26 } 27 return 0; 28 }
奇怪的比赛
某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
每位选手需要回答10个问题(其编号为1到10),越后面越有难度。答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。
每位选手都有一个起步的分数为10分。
某获胜选手最终得分刚好是100分,如果不让你看比赛过程,你能推断出他(她)哪个题目答对了,哪个题目答错了吗?
如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。例如:0010110011就是可能的情况。
你的任务是算出所有可能情况。每个答案占一行。
答案写在“解答.txt”中,不要写在这里!
思路:dfs,用一个数组存情况,注意数组记录情况的那一步一定要在进下一步dfs前。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 int a[15]={0}; 14 void dfs(int n,int score){ 15 if(n==11){ 16 if(score==100){ 17 for(int i=1;i<11;i++){ 18 cout<<a[i]; 19 } 20 cout<<endl; 21 return; 22 } 23 return ; 24 } 25 a[n]=0; 26 dfs(n+1,score-n); 27 a[n]=1; 28 dfs(n+1,score*2); 29 } 30 31 int main(){ 32 ios::sync_with_stdio(0); 33 dfs(1,10); 34 return 0; 35 }
转方阵
对一个方阵转置,就是把原来的行号变列号,原来的列号变行号
例如,如下的方阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
5 6 7 8
9 10 11 12
13 14 15 16
转置后变为:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
2 6 10 14
3 7 11 15
4 8 12 16
但,如果是对该方阵顺时针旋转(不是转置),却是如下结果:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
14 10 6 2
15 11 7 3
16 12 8 4
下面的代码实现的功能就是要把一个方阵顺时针旋转。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 void rotate(int *x,int rank){ 14 int* y=(int *)malloc(int(*)rank*rank); 15 for(int i=0;i<rank*rank;i++){ 16 y[rank*(rank-i%rank)+(rank-i%rank-1)]=x[i]; 17 } 18 for(int i=0;i<rank*rank;i++){ 19 x[i]=y[i]; 20 } 21 } 22 23 int main(){ 24 ios::sync_with_stdio(0); 25 int x[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; 26 int rank=4; 27 rotate(&x[0][0],rank); 28 for(int i=0;i<rank;i++){ 29 for(int j=0;j<rank;j++){ 30 printf("%4d",x[i][j]); 31 } 32 printf("\n"); 33 } 34 return 0; 35 }
大数乘法
对于32位字长的机器,大约超过20亿,用int类型就无法表示了,我们可以选择int64类型,但无论怎样扩展,固定的整数类型总是有表达的极限!如果对超级大整数进行精确运算呢?一个简单的办法是:仅仅使用现有类型,但是把大整数的运算化解为若干小整数的运算,即所谓:“分块法”。
如图【1.jpg】表示了分块乘法的原理。可以把大数分成多段(此处为2段)小数,然后用小数的多次运算组合表示一个大数。可以根据int的承载能力规定小块的大小,比如要把int分成2段,则小块可取10000为上限值。注意,小块在进行纵向累加后,需要进行进位校正。
以下代码示意了分块乘法的原理(乘数、被乘数都分为2段)。
1 void bigmul(int x, int y, int r[]) 2 { 3 int base = 10000; 4 int x2 = x / base; 5 int x1 = x % base; 6 int y2 = y / base; 7 int y1 = y % base; 8 9 int n1 = x1 * y1; 10 int n2 = x1 * y2; 11 int n3 = x2 * y1; 12 int n4 = x2 * y2; 13 14 r[3] = n1 % base; 15 r[2] = n1 / base + n2 % base + n3 % base; 16 r[1] = n2/base+n3/base+n4%base; // 填空 17 r[0] = n4 / base; 18 19 r[1] += r[2]/base; // 填空 20 r[2] = r[2] % base; 21 r[0] += r[1] / base; 22 r[1] = r[1] % base; 23 } 24 25 26 int main(int argc, char* argv[]) 27 { 28 int x[] = {0,0,0,0}; 29 30 bigmul(87654321, 12345678, x); 31 32 printf("%d%d%d%d\n", x[0],x[1],x[2],x[3]); 33 34 return 0; 35 }
放棋子
今有 6 x 6 的棋盘格。其中某些格子已经预先放好了棋子。现在要再放上去一些,使得:每行每列都正好有3颗棋子。
我们希望推算出所有可能的放法。下面的代码就实现了这个功能。
初始数组中,“1”表示放有棋子,“0”表示空白。
1 int N = 0; 2 3 bool CheckStoneNum(int x[][6]) 4 { 5 for(int k=0; k<6; k++) 6 { 7 int NumRow = 0; 8 int NumCol = 0; 9 for(int i=0; i<6; i++) 10 { 11 if(x[k][i]) NumRow++; 12 if(x[i][k]) NumCol++; 13 } 14 if(NumRow!=3||NumCol!=3) return false; // 填空 15 } 16 return true; 17 } 18 19 int GetRowStoneNum(int x[][6], int r) 20 { 21 int sum = 0; 22 for(int i=0; i<6; i++) if(x[r][i]) sum++; 23 return sum; 24 } 25 26 int GetColStoneNum(int x[][6], int c) 27 { 28 int sum = 0; 29 for(int i=0; i<6; i++) if(x[i][c]) sum++; 30 return sum; 31 } 32 33 void show(int x[][6]) 34 { 35 for(int i=0; i<6; i++) 36 { 37 for(int j=0; j<6; j++) printf("%2d", x[i][j]); 38 printf("\n"); 39 } 40 printf("\n"); 41 } 42 43 void f(int x[][6], int r, int c); 44 45 void GoNext(int x[][6], int r, int c) 46 { 47 if(c<6) 48 _f(x,r,c+1); // 填空 49 else 50 f(x, r+1, 0); 51 } 52 53 void f(int x[][6], int r, int c) 54 { 55 if(r==6) 56 { 57 if(CheckStoneNum(x)) 58 { 59 N++; 60 show(x); 61 } 62 return; 63 } 64 65 if(x[r][c]==1) // 已经放有了棋子 66 { 67 GoNext(x,r,c); 68 return; 69 } 70 71 int rr = GetRowStoneNum(x,r); 72 int cc = GetColStoneNum(x,c); 73 74 if(cc>=3) // 本列已满 75 GoNext(x,r,c); 76 else if(rr>=3) // 本行已满 77 f(x, r+1, 0); 78 else 79 { 80 x[r][c] = 1; 81 GoNext(x,r,c); 82 x[r][c] = 0; 83 84 if(!(3-rr >= 6-c || 3-cc >= 6-r)) // 本行或本列严重缺子,则本格不能空着! 85 GoNext(x,r,c); 86 } 87 } 88 89 int main(int argc, char* argv[]) 90 { 91 int x[6][6] = { 92 {1,0,0,0,0,0}, 93 {0,0,1,0,1,0}, 94 {0,0,1,1,0,1}, 95 {0,1,0,0,1,0}, 96 {0,0,0,1,0,0}, 97 {1,0,1,0,0,1} 98 }; 99 100 f(x, 0, 0); 101 102 printf("%d\n", N); 103 104 return 0; 105 }
煤球数目
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:算出每一层的煤球数量,然后加起来
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 14 int main(){ 15 ios::sync_with_stdio(0); 16 int c=0,sum=0; 17 for(int i=1;i<=100;i++){ 18 c+=i; 19 sum+=c; 20 } 21 cout<<sum<<endl; 22 return 0; 23 }
凑算式
B DEF
A + --- + ------- = 10 (如果显示有问题,可以参见【图1.jpg】)
C GHI
A + --- + ------- = 10 (如果显示有问题,可以参见【图1.jpg】)
C GHI
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <cstring> 7 #include <stdio.h> 8 #define lowbit(x) x&(-x) 9 10 using namespace std; 11 const int maxn=1e5+10; 12 typedef long long ll; 13 int a[9]={1,2,3,4,5,6,7,8,9}; 14 int fun(){ 15 int A=a[0]; 16 int b=a[1]; 17 int c=a[2]; 18 int def=a[3]*100+a[4]*10+a[5]; 19 int ghi=a[6]*100+a[7]*10+a[8]; 20 if(A*c*ghi+b*ghi+c*def==10*c*ghi){ 21 return 1; 22 } 23 return 0; 24 } 25 int main(){ 26 ios::sync_with_stdio(0); 27 int ans=0; 28 29 while(next_permutation(a,a+9)){ 30 ans+=fun(); 31 } 32 cout<<ans<<endl; 33 return 0; 34 }