约瑟夫环
n个人从第k个开始报数,报到m的人出局,环形不断报数,求最后一个人的编号
复杂度较高的解法,是O(n),O(nm)
可以跳过约瑟夫环报数每个周期的等差数列,大大降低复杂度,这里只记录一下代码,别人的代码懒得写了,但是验证过了是正确的
ll solve(ll n,ll k,ll s)//n人数,k报数周期,s报数起始位置
{
if(k==1) return (n-1+s)%n;
ll ans=0;
//ans=(ans+k)%i
for(ll i=2;i<=n;)
{
if(ans+k<i) //跳跃
{
ll leap;
if((i-ans-1)%(k-1)==0) leap=(i-ans-1)/(k-1)-1;
else leap=(i-ans-1)/(k-1);
if(i+leap>n) return ((ans+(n+1-i)*k)+s)%n;
i+=leap;
ans+=leap*k;
}
else
{
ans=(ans+k)%i;
i++;
}
}
return (ans+s)%n;
}