首页 > 代码库 > POJ 3358
POJ 3358
此题的主要还是如何把小数化作分数来解答。
设p/q。对于二进制(三进制,四进制一样),若p>q便商1,取mod,p*2-->p,然后再作p/q,若p<q,商0。
于是有,在去公约数GCD后,p/q的小数是否重复,和上述步骤p是否重复是一致的。若重复,得方程
p*2^i=p*2^j (mod q)。则有p*2^i(2^(j-i)-1)=0 (mod q)。即q|2^i(2^(j-i)-1)。而要求最小,只需使两者相等。即q中2的幂即为i。利用欧拉定理也可求出j-i的最小值。
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#define LL __int64using namespace std;LL fac[10000]; int cnt;LL gcd(LL a,LL b){ if(b==0) return a; return gcd(b,a%b);}LL Euler(LL m){ LL res=m; LL k=(LL)sqrt((double)m); for(LL i=2;i<=k;i++){ if(m%i==0){ res=res-res/i; while(m%i==0) m/=i; } } if(m>1) res=res-res/m; return res;}LL quick(LL a,LL b,LL m){ LL ans=1; while(b){ if(b&1){ ans=(ans*a)%m; } b>>=1; a=(a*a)%m; } return ans;}int main(){ LL p,q; int kase=0; while(scanf("%I64d/%I64d",&p,&q)!=EOF){ p=p%q; LL g=gcd(p,q); p/=g; q/=g; LL ai=0,aj=0; while(q%2==0){ ai++; q/=2; } LL phi=Euler(q); cnt=0; LL k=(LL)sqrt((double)phi); for(LL i=1;i<=k;i++){ if(phi%i==0){ fac[cnt++]=i; fac[cnt++]=phi/i; } } sort(fac,fac+cnt); for(int i=0;i<cnt;i++){ LL ans=quick((LL)2,fac[i],q); if(ans==1){ aj=fac[i]; break; } } printf("Case #%d: %I64d,%I64d\n",++kase,ai+1,aj); } return 0;}
POJ 3358
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。