丢手绢(暴力)

xiaoxiao2021-02-28  68

丢手绢

六一儿童节到了,小朋友们在玩丢手绢的游戏。总共有C个小朋友,编号从1到C,他们站成一个圈,第i(1<i<=C)个人的左边是i-1,第1个人的左边是C。第i(1<=i<C)个人的右边是i+1,第C个人的右边是1。然后再给出一个常数E。刚开始的时候1号小朋友拿着手绢,接下来游戏开始,在游戏的每一轮,拿手绢的人会把手绢向右边传递E-1个人,拿到手绢的人退出圈,把手绢递给他右边的小朋友,剩下的人向中间挨紧,把圈中的空位补满。然后开始下一轮,如此往复。直到圈中只剩一个人。比如C=6,E=5的时候,出圈的顺序是5,4,6,2,3,最后1号小朋友留在了圈中。

现在有2G个小朋友,要求一个最小的常数E,使得这2G个小朋友玩了G轮游戏之后,出圈的小朋友编号刚好是G+1到2G。

Input 多组测试数据。 每一行给出一个整数G( 0 < G < 14),G=0的时候表示输入结束。 Output 输出多行,表示每一组数据的答案。 Sample Input 3 4 0 Sample Output 5 30

中文题面就不讲提意了;

这题类似约瑟夫问题,一共就13个数,暴力打表出所有结果,然后O(1)查询就行了;我的打表很慢很慢很慢,打表的时候出去浪了一圈回来还差一个数每出来。。。还是别看我的打表方法,感觉这题可以利用约瑟夫环的推导公式打表,应该效率高一点;

AC代码:

#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<stack> using namespace std; int n,ans[14]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};//处理完后的结果 bool vis[30]; bool check(int k,int v) { int gg=v%(2*k); if(gg>=1&&gg<=k) return false; memset(vis,true,sizeof(vis)); int cnt=1,tmp=1; while(cnt++<=k) { int f=0; while(true) { if(vis[tmp]) f++; if(f==v) { vis[tmp]=false; if(tmp>=1&&tmp<=k) return false; tmp++; tmp=tmp>2*k?tmp-2*k:tmp; break; } tmp++; tmp=tmp>2*k?tmp-2*k:tmp; } } for(int i=k+1;i<=2*k;i++) if(vis[i]) return false; return true; } void init() { for(int i=1;i<=13;i++) { int p=1; while(!check(i,++p)); ans[i]=p; cout<<p<<endl; } } int main() { //init(); while(~scanf("%d",&n)&&n) { printf("%d\n",ans[n]); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-83404.html

最新回复(0)