poj3358 Period of an Infinite Binary Expansion

来源:互联网 发布:js获取北京时间 编辑:程序博客网 时间:2024/05/29 07:59



题目大意:

给你一个分数,就他二进制的循环节。求开始循环的点和循环长度。


思路:


已知t*2^phi(r)=t (mod r),先求出phi(r),然后求phi(r)的因子,求一个最小符合条件的。

这样就可以大大缩小了查找的范围。




#include <iostream>#include <cmath>#include <stdio.h>#include <map>#include <algorithm>using namespace std;#define LL long long #define min(a,b) a<b?a:bLL gcd(LL a,LL b){if(b==0) return a;return gcd(b,a%b);}LL phi(LL p){LL ret=p;for(LL i=2;i*i<=p;++i){if(p%i==0){ret=ret/i*(i-1);p/=i;while(p%i==0) p/=i;}}if(p!=1)ret=ret/p*(p-1);return ret ;}LL pow2_mod(LL k,LL md){if(k==0) return 1;if(k==1)return 2%md;LL b=pow2_mod(k/2,md);b=(b*b)%md;if(k&1)return 2*b%md;return b;}int main(){LL p,q,i,cnt=0,period,j;while(~scanf("%I64d/%I64d",&p,&q)){j=1<<29;//if(!p){ printf("Case #%I64d: 1,1 \n",++cnt);continue; } period=0;LL g=gcd(p,q);p/=g;q/=g;i=1;while(q%2==0){q/=2;i++;}LL x=phi(q);for(int k=2;k*k<=x;++k){if(x%k==0){if(k<j){if(pow2_mod(k,q)==1)j=k;}LL temp=x/k;if(temp<j)if(pow2_mod(temp,q)==1)j=temp;}}if(j>(1<<28))period=x;else period=j;printf("Case #%I64d: %I64d,%I64d \n",++cnt,i,period);}}


0 0