SWQ的数字游戏
试题描述
|
SWQ近期编程水平有了很大提高,于是她总想设计出一款游戏供社团的队员们玩,爱玩游戏的LJX一直就期待着。这不,今天SWQ就设计了这样一个游戏:
两个玩家A和B做猜数字游戏,首先他们会确定一个正整数n,然后A从1-n中选定一个整数,这个数暂时对B保密,注意一旦选定之后只有游戏结束都不能修改这个数字,假设这个数字是x,然后游戏开始,每次B都可以在1-n中选择一个整数(假设这个数字是y),然后A会回答他x和y的最大公约数,B可以利用之前A回答的结果决定下一轮中他所选择的数字,如果在某一时刻,B可以用A回答的结果推理出A选择的数字,则游戏结束。 假设n=6,如果A选定了数字2,然后第一轮B询问了数字6,A回答2,这时B可以推断出A手中的数字只能是2或者4,然后B询问数字2,就可以知道A手中的数字了(这只是一种可能的游戏进行方式,可能并非最优策略), 问:对于一个确定的正整数n,在最坏的情况下游戏需要进行几轮?即无论A选择了什么数字,B都可以保证有一个策略使得游戏在这么多轮之内结束。假设游戏者都遵循最优策略进行。 |
输入
|
第一行包含一个正整数m,表示共有m组测试数据。第二行包含m个正整数,依次表示每一组测试数据中的正整数n。两数间用一个空格分隔。
|
输出
|
共m行,每行仅包含一个数,依次表示m组测试数据的结果。
|
输入示例
|
4
2 3 5 6 |
输出示例
|
1
2 3 2 |
其他说明
|
数据范围:1<=m<=10,2<=n<=10000。
|
需要用到素数表。
1 #include<iostream> 2 3 using namespace std; 4 5 int n,cnt,prime[2005]; 6 bool mark[10005]; 7 8 void findprime()//高效筛素数:统计10000以内素数的个数为:cnt,并建立素数表 9 {//将10000以内cnt个素数,依次存储在prime[1], prime[2],......,prime[cnt]中 10 for(int i=2;i<=10000;i++) //mark[i]标记i是否为素数:0为素数,1为非素数 11 { 12 if(!mark[i]) prime[++cnt]=i; 13 for(int j=1;prime[j]*i<=10000 && j<=cnt;j++) 14 { 15 mark[prime[j]*i]=1; 16 if(i%prime[j]==0) break; 17 } 18 } 19 } 20 21 int main() 22 { 23 int i,k,m,n; 24 findprime(); //建立素数表存储在数组prime[]中,共cnt个 25 scanf("%d",&m);//总共有m组测试数据 26 for(k=1;k<=m;k++) 27 { 28 memset(mark,0,sizeof(mark)); //数组mark[]辅助prime[]筛素数,先清零 29 scanf("%d",&n); //第k组测试数据有1到n的整数可供游戏者选择,即b询问的数 30 int now=1,ans=0; 31 for(i=cnt;i>=now;i--) 32 { 33 if(!mark[i] && prime[i]<=n) //第i个素数不超过n。!mark[i]是 mark[i]!=1 的意思,为了判断当前素数是否用过 34 { 35 int sum=prime[i];//当前的素数 36 mark[i]=1;ans++;//标记当前素数用过 37 while(sum*prime[now]<=n) //从小到大找素数,直到找到正确答案 38 { 39 sum*=prime[now]; 40 mark[now]=1; //标记 41 now++; 42 } 43 } 44 } 45 printf("%d\n",ans); 46 } 47 //system("pause"); 48 return 0; 49 }