原来并不知道约瑟夫环还可以递推直接解orz
约瑟夫问题的递推公式:
设f[n]表示一共n个人,数到k出局,这样最后的winner (n个人从0开始标号,即0--n-1)
f[n]=(f[n-1]+k)%n (注意%n里这个n也是变量
初值f[1]=0
【公式的详细证明可以refer这里:http://blog.csdn.net/a725sasa/article/details/11664375 】
不过本题n很大,O(n)仍然会爆
注意到公式中的%n:如果f[n-1]+k小于n,那么就不用再mod了
如果f[n-1]+若干个k还是很小,就可以一次多跳几步
Reference:http://blog.csdn.net/gyarenas/article/details/9073045
1 //f[1]=0 f[i]=(f[i-1]+m)%i 2 //ty=(tx+m)%i 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 #define LL long long 8 LL n,k; 9 10 LL solve(LL n,LL k) 11 { 12 LL i=2; 13 LL tx=0; 14 while(i<=n) 15 { 16 LL x=(i-1-tx)%(k-1)?(i-1-tx)/(k-1):(i-1-tx)/(k-1)-1; 17 if(tx+k<i) 18 { 19 if(i+x>n) 20 { 21 tx=tx+(n+1-i)*k; 22 return(tx); 23 } 24 tx=tx+x*k; 25 i+=x; 26 } 27 else 28 { 29 tx=(tx+k)%i; 30 i++; 31 } 32 } 33 return(tx); 34 } 35 36 int main() 37 { 38 while(scanf("%I64d%I64d",&n,&k)!=EOF) 39 { 40 int i=2; 41 LL tx=0; 42 if(k==1) 43 { 44 tx=(n-1)%n; 45 } 46 else 47 tx=solve(n,k); 48 tx=(tx+1)%n; 49 if(tx==0) tx+=n; 50 printf("%I64d\n",tx); 51 } 52 }
时间: 2024-09-30 14:37:41