标签:multi for 快速 font 因子 href continue tin 数据
把分数转化为二进制小数,找出二进制小数的最小循环节长度以及开始位置。
有理数n的第k位小数应为(n*2^k)mod\ 2
这里用分数p/q表示,则第 k 位小数位$(\frac{p}{q}*2^k)mod\ 2=(p*2^k)/q mod 2$,同时后k位小数为$(p*2^k )mod\ q$;若周期开始位置位x,长度为y,则$ (p*2^x\ mod\ q\equiv(p*2^{(x+y)} \ mod\ q$。y)
那么有
$q|p*2^x*(2^y-1)$
由于p、q互素,则$q|2^x*(2^y-1)$
显然,x的最小值即为q中素因子2的幂;而$q=q<<x$后,$2^y\equiv1\ mod\ q$,y的一个值即为$\varphi(q)$,y的最小值为$\varphi(q)$的一个因数。
1 #include<cstring> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int Ma=1000006; 9 long long q,p; 10 11 long long phi(long long n) 12 { 13 long long ret=n; 14 for(int i=2;i*i<=n;i++) 15 { 16 if(n%i==0) 17 { 18 while(n%i==0) 19 { 20 ret-=ret/i; 21 while(n%i==0)n/=i; 22 } 23 } 24 } 25 if(n>1)ret=ret-ret/n; 26 return ret; 27 } 28 29 long long gcd(long long x,long long y) 30 { 31 if(y==0)return x; 32 else return gcd(y,x%y); 33 } 34 35 long long qmulti(long long a,long long b,long long mo) 36 { 37 long long ret=0; 38 while(b) 39 { 40 if(b&1)ret=(ret+a)%mo; 41 b>>=1; 42 a=(a+a)%mo; 43 } 44 return ret; 45 } 46 47 long long qpow(long long a,long long b,long long mo) 48 { 49 long long ret=1; 50 while(b) 51 { 52 if(b&1)ret=qmulti(ret,a,mo)%mo; 53 a=qmulti(a,a,mo)%mo; 54 b>>=1; 55 } 56 return ret%mo; 57 } 58 59 int main() 60 { 61 int cnt=0; 62 while(scanf("%lld/%lld",&p,&q)!=EOF) 63 { 64 cnt++; 65 if(p==0) 66 { 67 printf("Case #%d: 1,1 \n",cnt); 68 continue; 69 } 70 long long g=gcd(p,q); 71 p/=g;q/=g; 72 long long x=1,y; 73 while(!(q&1))q>>=1,x++; 74 y=phi(q); 75 long long t=y; 76 for(long long i=2;i<=t/i;i++) 77 { 78 while(y%i==0&&(qpow(2,y/i,q)==1)) 79 { 80 y/=i; 81 } 82 } 83 printf("Case #%d: %lld,%lld \n",cnt,x,y); 84 } 85 return 0; 86 }
poj3358 Period of an Infimite Bimary Expansion
标签:multi for 快速 font 因子 href continue tin 数据
原文地址:https://www.cnblogs.com/LiqgNonqfu/p/10807141.html