码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3089 约瑟夫环

时间:2015-05-15 21:08:20      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

原来并不知道约瑟夫环还可以递推直接解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 }
View Code

 

hdu 3089 约瑟夫环

标签:

原文地址:http://www.cnblogs.com/pdev/p/4506757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!