【题意】
n个城市(标号1,2,....,n)轮流断网,先停1号城市,然后每m个城市断网,断了的就不用计入在内了。
【分析】
约瑟夫环杀人游戏的一个变种。
自己总算能用之前的公式套了。
我们已知的结论是:
f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n],递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1) //注意这里%i,i表示当前算的数,计算f[2],则i=2,计算f[3],则i=3,开始我搞错了。
本题1号城市首先断网,所以对于给定的n,我只需要计算出最小的m,使得f[n-1]=0即可;
道理是:1号城市已经断网了,再以后的循环就不会再有1介入,要使2号城市最后断网(最后胜利者)也就是使剩下n-1个城市的第一个城市成为胜利者,而我们公式里的编号是从0开始的,第一个城市的编号在答案里就是0;
依据上面的分析,题目n,3<=n<150,我们可以先处理出所有的n,对于每一个n,枚举m,当f[n]=0时,我们就得到了结果,保存之,具体见代码。
【代码】
/*2244 Accepted 136K 16MS C++ 518B 2011-01-19 20:45:46 */
#include<stdio.h>
#include<string.h>
int f[152],ans[152];
void Init(){
int m,i,j,count=0,flag=0;
memset(f,0,sizeof(f)); f[1]=0;
for(i=2;i<150;i++){
for(m=2;;m++){
for(j=2;j<=i;j++)
f[j]=(f[j-1]+m)%j; //j,当前人数;
if(f[i]==0){ ans[i+1]=m; break; }
}
}
}
int main()
{
int k;
Init();
while(scanf("%d",&k),k)
printf("%d/n",ans[k]);
}
后来找了网上的一篇题解:
http://brianyang1106.blog.163.com/blog/static/137602892201002734755225/