求n个人,每次报m次出队,求第k个出队的人
f
[
n
]
[
k
]
=
(
f
[
n
−
1
]
[
k
−
1
]
+
m
−
1
)
%
n
f[n][k]=(f[n-1][k-1]+m-1)\%n
f[n][k]=(f[n−1][k−1]+m−1)%n
时间复杂度为
O
(
k
)
O(k)
O(k)
当
k
k
k很大但是
m
<
<
n
m<<n
m<<n时,可以把多次
(
m
−
1
)
(m-1)
(m−1)加在一起,一起取模
#include <bits/stdc++.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
long long n,m,k,i,s,mod,num;
int T,t,l;
int main()
{
scanf("%d",&T);
fo(t,1,T)
{
scanf("%lld%lld%lld",&n,&k,&m);
if (m == 1) {printf("Case #%d: %lld\n",t,k); continue;}
mod = n - k + 1;
s = m - 1; s = s % mod;
while (1)
{
num = (mod - s) / (m - 1);
num = min(num,n-mod);
s += num * m;
mod = mod + num;
s = s % mod;
if (mod == n) break;
s += m; mod++;
s = s % mod;
if (mod == n) break;
}
printf("Case #%d: %lld\n",t,s+1);
}
return 0;
}