HDU 3089 (快速约瑟夫环)
Posted kimsimple
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3089 (快速约瑟夫环)相关的知识,希望对你有一定的参考价值。
Josephus again
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 652 Accepted Submission(s): 181
each case have two integer, n, k. (1<= n <= 10^12, 1 <= k <= 1000)
#include "iostream" #include "cstdio" using namespace std; #define LL long long int main(){ LL gg, n, k; while(~scanf("%lld%lld",&n,&k)){ gg=0; for(LL i=2; i<=n; i++){ gg=(gg+k)%i; } printf("%lld\\n",(LL)gg+1); } return 0; }
Time Limit Exceeded
second try:
约瑟夫环,但是n超大
快速约瑟夫环
约瑟夫环递推公式,n为人数,k为步长。
f(1)=0
f(n)=[f(n-1)+k]%i i∈[2,n]
f(n)还要经过起始位置修正,设起始位置为s,即ans=[f(n)+s]%n。
基本约瑟夫环优化就是当k=1的时候,每次递推就是在+1,可以直接算出来快速跳过,f(n)=f(1)+n-1
当n超大的时候,可以照着这种思路快速简化递推过程。在递推后期,f(x)+k在很长的周期内<i,假设有m个周期,
那么这些周期合并后的结果相当于f(x)+m*k。可以快速跳过。条件限制是: f(x)+m*k<i+(m-1)
可以推出来:
当m=1时,条件限制: f(x)+k<i
当m=2是,条件限制: f(x+1)+k<i+1=f(x)+2*k<i+1
当m=m时,条件限制:f(x)+m*k<i+(m-1)
化简有m<(i-f(x)-1)/(k-1),若能整除,就是(i-f(x)-1)/(k-1)-1,否则就是(i-f(x)-1)/(k-1)直接取整。
这样,i+=m,f(x)+=m*k,快速跳过了中间过程。
若i+m>n,说明快速跳越界了,这时候可以直接算出f(n)=f(x)+(n-i-1)*m。
#include "cstdio" #define LL long long LL solve(LL n,LL k,LL s=1) { 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; } int main() { //freopen("in.txt","r",stdin); LL n,k; while(scanf("%I64d%I64d",&n,&k)!=EOF) { LL ans=solve(n,k); if(ans==0) printf("%I64d\\n",n); else printf("%I64d\\n",ans); } }
感谢:http://www.cnblogs.com/neopenx/p/4505298.html
算法性能考验!十分重要!
以上是关于HDU 3089 (快速约瑟夫环)的主要内容,如果未能解决你的问题,请参考以下文章