这道题开始一看还真没有什么思路,后面看了一下数据范围,数据不大
就直接暴力枚举求解了,最后也过了。
后来在网上查了一下,有人讲这是一个关于约瑟夫环的问题,就去看了一下约瑟夫环的相关知识
才发现是原来是有公式的。。。。。。。。。。。
下面是关于约瑟夫环问题的一篇文章的链接
http://blog.csdn.net/sunandice/article/details/6560889
代码如下:
第一个是直接枚举求解,第二个是公式法
//直接枚举m求解
#include<iostream>
using namespace std;
int main()
{
int a[155],n,i,b[155];
while(cin>>n&&n)
{
for(i=0;i<n;i++)
{
a[i]=i+1;
b[i]=a[i];
}
int m=1,sum,cnt,k;
while(1)
{
int flag=0;
sum=1; cnt=0; a[0]=0; k=1;
while(1)
{
if(a[k])
cnt++;
if(cnt==m)
{
a[k]=0;
sum++;
cnt=0;
}
k=(k+1)%n; //循环队列思想
if(a[1]&&sum==n-1)
{
flag=1;
break;
}
if(!a[1]&&sum<=n-1)
break;
}
for(i=0;i<n;i++)//开始时没考虑到每一次模拟都会导致a[]变化
a[i]=b[i]; //所以总是陷入死循环;b[]的作用就是每枚举一次m后重新恢复a[]的值
if(flag)
{
cout<<m<<endl;
break;
}
m++;
}
}
return 0;
}
//问题二:求出最后出圈的那个人的序号
//方法一:模拟,最后留下的元素就是所求元素
//方法二:利用递推公式 f[1]=0 f(i)=f(f[i-1]+m)%i;
#include<iostream>
using namespace std;
int n,m;
bool judge()
{
int from = 0;
for(int i = 2 ;i < n ; i ++)
from = (from + m)%i;
if(from + 1 == 1) return true;//最后剩下的那栋楼的最开始的编号是1的话,返回true
else return false;
}
int main()
{
while(cin>>n&&n)
{
m=1;
while(!judge())
++m;
cout<<m<<endl;
}
return 0;
}