问题描述: 有 n 个人 围成一个环 从第start个人 开始 数 n_th个人 数到第n_th个人时 这个人出去 ,接着从这个人后再数n_th,一直循环,求最后一个出去得人 的序号
比如: n=9,start=1,n_th=5
1 2 3 4 5 6 7 8 9 a[4] 第五个出去得:
1 2 3 4 6 7 8 9
然后继续数 5个 去除a[0] 第一个
2 3 4 6 7 8 9
.....................
the sequence is: 5 1 7 4 3 6 9 2 8
the winner is: 8
这个过程是上述所说的一样,这个解决方案一共有两种解决方案
我们先看第一种 数组模拟
#include <iostream>
using namespace std;
#include <stdlib.h>
int main()
{
int n,s,n_th;
int a[1005];
while (cin>>n>>s>>n_th)
{
int i,temp;
for (i=0; i<n; ++i)
a[i]=i+1;
temp=s-1;
cout<<"the sequence is: ";
while (n>0)
{
temp=(temp+n_th-1)%n;
cout<<a[temp]<<" ";
for (i=temp+1; i<n; i++)
a[i-1]=a[i];
--n;
}
cout<<endl<<"the winner is: "<<a[0]<<endl;
}
return 0;
}
第二种是数学解决方案:
具体推导过程如下:
假如我们知道这个子问题的解:例如ans是最终的胜利者,那么根据上面这个表把这个ans变回去
下面的是 以 第一个人为起点的即 start=1;
ans=0;
∵ k=n_th%n;
∴ ans = ans+k = ans+ n_th%n ; 而 x+ n_th%n 可能大于n
∴ans= (ans+ n_th%n)%n = (ans+n_th)%n
得到 ans=(ans+n_th)%n
i 为 起点start
a[1]=0;
a[i]=(a[i]+n_th)%i;
现在换成是第start个人为起点时,也是一样的
#include <iostream>
using namespace std;
#include <stdlib.h>
int main()
{
int n,s,n_th,res;
int a[1005];
while (cin>>n>>s>>n_th)
{
int i;
for (i=0; i<n; ++i)
a[i]=i+1;
res=1;
for (i=2; i<=n; i++)
{
res=(res+n_th)%i;
if (0==res)
res=i;
}
//此时 res为 s=1的情况
res=(res-1+s-1)%n+1;//变换
cout<<"the winner is: "<<res<<endl;
}
return 0;
}