猜数字游戏的提示
题目:
给定答案序列和用户猜的序列,统计有多少数字位置正确(A),有多少数字在两个序列都出现过但位置不对(B)。
输入包含多组数据,每组输入第一行为序列长度n,第二行是答案序列,接下来是若干猜测序列。
猜测序列全0时该组数据结束。n=0时输入结束。
样例输入:
4
1 3 5 5
1 1 2 3
4 3 3 5
6 5 5 1
6 1 3 5
1 3 5 5
0 0 0 0
10
1 2 2 2 4 5 6 6 6 9
1 2 3 4 5 6 7 8 9 1
1 1 2 2 3 3 4 4 5 5
1 2 1 3 1 5 1 6 1 9
1 2 2 5 5 5 6 6 6 7
0 0 0 0 0 0 0 0 0 0
0
样例输出:
Game 1:
(1,1)
(2,0)
(1,2)
(1,2)
(4,0)
Game 2:
(2,4)
(3,2)
(5,0)
(7,0)
分析:按照题目意思,不光要计算跟答案序列在位置上正确的数字有多少个,还要计算猜测序列有多少个数字出现跟答案序列一样但是位置不对的(已经出现过的对应数字在对应位置上的数字不计算)。
这里特别要注意的是不能把重复出现的数字也算进去(设(sum1,sum2-sum1)),在解决这个问题的时候想当然的利用答案序列作为根无脑遍历猜测数列,后来发现只能解决一边序列没有重复,另一边还是会继续算进去,后来就想到了遍历数字1~9,分别计算两个序列的出现该数字的个数,取出现次数小的加在sum2上。
代码如下:
#include<iostream>
using namespace std;
#define maxn 101
int main(){
int count1,count2,i,j,n,sum1,sum2,a[maxn],b[maxn],game=1;
while(cin>>n){
if(n==0)break;
cout<<"game "<<game++<<":"<<endl;
for(i=0;i<n;i++)
cin>>a[i];
while(true){
sum1=0,sum2=0;
for(i=0;i<n;i++){
cin>>b[i];
if(b[i]==a[i])sum1++;
}
if(b[0]==0)break;
for(int num=1;num<=9;num++){
count1=0,count2=0;
for(i=0;i<n;i++){
if(a[i]==num)count1++;
if(b[i]==num)count2++;
}
count1<count2?sum2+=count1:sum2+=count2;
}
cout<<"("<<sum1<<","<<sum2-sum1<<")"<<endl;
}
}
return 0;
}
运行截图:
生成元
题目:
如果x加上x的各个数字之和得到y,就说x是y的生成元。给出n(1≤n≤100000),求最小生成元。无解输出0。例如,n=216,121,2005时的解分别为198,0,1979。
思路:按照题目意思,m总小于n,把这题类比于传智杯的第三题(不能用函数求一个数的开方(取整)),直接从i=1开始进行遍历计算,这里的遍历计算需要用到中间值x,而y作为底数;把i赋值给x,y,当得到x%10的值以后改变x的值x/=10,达到动态改变x的值而不改变i的目的,最后再判断如果有n==y,则输出i,由于此时第一个得出的i最小,就可以break掉重新开始;否则判断当i=临界值maxn-1的时候即为无解,返回0.
代码如下:
#include<iostream>
using namespace std;
const int maxn=100000;
int main(){
int x,y,n,m,i;
while(cin>>n){
for(i=1;i<maxn;i++){
x=i,y=i;
while(x){
y+=x%10; x/=10;
}
if(n==y){
cout<<i<<endl;
break;
}
if(i==maxn-1)cout<<"0"<<endl;
}
}
return 0;
}
运行截图: