poj 3358 Period of an Infinite Binary Expansion

由乘2取整得到分数的小数位,可以找到规律!!!

例如:1/10,2/10,4/10,8/10,16/10,32/10,64/10……

取整后:1/10,2/10,4/10,8/10,6/10,2/10,4/10……

这样我们就发现规律了!!!

也就是对于p/q而言,要满足2^x=2^y mod q (gcd(p,q)==1);

化简:2^x*(2^(x-y)-1) = 0 mod q;

q里面2的倍数有多少个,就是最小的循环起始位置。

继而化简:2^(x-y) = 1 mod q' (q'除以2的倍数之后的值)

也就是求2^t = 1 mod q'

由欧拉定理知道:t=phi(q');但是这求出的t不一定是最小的,所以应该枚举t的约数,继而得到答案……

链接http://poj.org/problem?id=3358

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<algorithm>
  4 #include<iomanip>
  5 #include<cmath>
  6 #include<string>
  7 using namespace std;
  8 int prime[5000],m;
  9 bool f[5001];
 10 void init()
 11 {
 12     __int64 i,j;
 13     m=0;
 14     for(i=2;i<=5000;i++)
 15     {
 16         if(f[i]==0)
 17         {
 18             prime[m++]=i;
 19             for(j=i*i;j<=5000;j+=i)
 20                 f[j]=1;
 21         }
 22     }
 23 }
 24 __int64 gcd(__int64 a,__int64 b)
 25 {
 26     __int64 t;
 27     if(a<b) swap(a,b);
 28     while(b)
 29     {
 30         t=a;
 31         a=b;
 32         b=t%b;
 33     }
 34     return a;
 35 }
 36 __int64 euler(__int64 n)
 37 {
 38     __int64 ans=1;
 39     int i;
 40     for(i=0;i<m&&prime[i]<=n;i++)
 41     {
 42         if(n%prime[i]==0)
 43         {
 44             n/=prime[i];
 45             ans*=prime[i]-1;
 46             while(n%prime[i]==0)
 47             {
 48                 ans*=prime[i];
 49                 n/=prime[i];
 50             }
 51         }
 52     }
 53     if(n!=1)
 54         ans*=n-1;
 55     return ans;
 56 }
 57 __int64 pows(__int64 a,int b,__int64 m)
 58 {
 59     __int64 ans=1;
 60     while(b)
 61     {
 62         if(b&1)
 63             ans=ans*a%m;
 64         b>>=1;
 65         a=a*a%m;
 66     }
 67     return ans;
 68 }
 69 int main()
 70 {
 71     init();
 72     __int64 a,b,q,g,mmin;
 73     int i,j,p,k=0;
 74     while(scanf("%I64d/%I64d",&a,&b)!=EOF)
 75     {
 76         if(a==0)
 77             printf("Case #%d: %d,%I64d\n",++k,1,1);
 78         g=gcd(b,a);
 79         a=a/g;b=b/g;
 80         i=1;
 81         while(b%2==0)
 82         {
 83             b/=2;
 84             i++;
 85         }
 86         q=euler(b);j=i;
 87         mmin=q;
 88         for(i=1;i*i<=q;i++)
 89         {
 90             if(q%i==0)
 91             {
 92                 if(pows(2,i,b)==1)
 93                 {
 94                     mmin=i;
 95                     break;
 96                 }
 97                 p=q/i;
 98                 if(pows(2,p,b)==1&&p<mmin) mmin=p;
 99             }
100         }
101         printf("Case #%d: %d,%I64d\n",++k,j,mmin);
102     }
103     return 0;
104 }
View Code

 

posted @ 2013-07-16 10:53  _随心所欲_  阅读(183)  评论(0编辑  收藏  举报