poj 3358 Period of an Infinite Binary Expansion——欧拉函数+费马小定理
2011-09-06 19:12
423 查看
题目意思是给定m,n问你 m/n的二进制表示的最大循环节开始位置和长度。
找了一些题解,发现没有满意的,discuss里面的分析已经很好了。。
我们可以观察一下1/10这组数据,按照二进制转换法(乘二法),我们可以得到:
1/10 2/10 4/10 8/10 16/10 32/10 ...
然后都分子都尽可能减去10,得到:
1/10 2/10 4/10 8/10 6/10 2/10 ...
这时候,发现出现了重复,那么这个重复就是我们要求的最小循环。
抽象出模型如下:对p/q
首先p'=p/gcd(p,q)
q'=q/gcd(p,q);
然后我们就是求p'*2^i == p'*2^j (mod q') (“==”表示同余,i<j;
经过变换得到:
p'*2^i*(2^(j-i)-1) ==0 (mod q')
也就是 q' | p'*2^i*(2^(j-i)-1)
由于gcd(p',q')=1,
得到: q' | 2^i*(2^(j-i)-1)
因为2^(j-i)-1为奇数,所以q'有多少个2的幂,i就是多少,而且i就是循环开始位置的前一位。
那么令q''为q'除去2的幂之后的数
此时 q'' | 2^(j-i)-1
也就是求出x,使得 2^x ==1 (mod q'')
因此我们还要枚举phi(q)的因子,判断有 2 ^ x == 1(mod q) ,取最小的x(PS:先开始这个地方写搓了,很容易错的呀。。)
找了一些题解,发现没有满意的,discuss里面的分析已经很好了。。
我们可以观察一下1/10这组数据,按照二进制转换法(乘二法),我们可以得到:
1/10 2/10 4/10 8/10 16/10 32/10 ...
然后都分子都尽可能减去10,得到:
1/10 2/10 4/10 8/10 6/10 2/10 ...
这时候,发现出现了重复,那么这个重复就是我们要求的最小循环。
抽象出模型如下:对p/q
首先p'=p/gcd(p,q)
q'=q/gcd(p,q);
然后我们就是求p'*2^i == p'*2^j (mod q') (“==”表示同余,i<j;
经过变换得到:
p'*2^i*(2^(j-i)-1) ==0 (mod q')
也就是 q' | p'*2^i*(2^(j-i)-1)
由于gcd(p',q')=1,
得到: q' | 2^i*(2^(j-i)-1)
因为2^(j-i)-1为奇数,所以q'有多少个2的幂,i就是多少,而且i就是循环开始位置的前一位。
那么令q''为q'除去2的幂之后的数
此时 q'' | 2^(j-i)-1
也就是求出x,使得 2^x ==1 (mod q'')
因此我们还要枚举phi(q)的因子,判断有 2 ^ x == 1(mod q) ,取最小的x(PS:先开始这个地方写搓了,很容易错的呀。。)
a27400 | 3358 | Accepted | 400K | 0MS | G++ | 1258B | 2011-09-06 18:57:36 |
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> typedef long long LL; LL gcd(LL a,LL b) { if(b==0) return a; else return gcd(b,a%b); } LL euler(LL n) { LL i; LL total=n; for(i=2;i*i<=n;i++) { if(n%i==0) { total=total/i*(i-1); while(n%i==0) n/=i; } } if(n!=1) total=total/n*(n-1); return total; } LL quickmod(LL a,LL n,LL p) { if(n==0) return 1%p; if(n==1) return a%p; a%=p; LL ans=quickmod(a,n/2,p)%p; ans=ans*ans%p; if(n&1) ans=ans*a%p; return ans; } int main(void) { LL p,q; LL cas=0; char ch; while(scanf("%lld%c%lld",&p,&ch,&q)==3) { LL temp=gcd(p,q); p=p/temp; q=q/temp; LL i=1,j=-1; while(q%2==0) { q/=2; i++; } LL phi=euler(q); LL k; for(k=2;k*k<=phi;k++) { if(phi%k==0) { if(quickmod(2,k,q)==1) { if(j==-1) j=k; else if(j>k) j=k; break; } else { LL temp=phi/k;//先开始忘记写else这块了。。。 if(quickmod(2,temp,q)==1) { if(j==-1) j=temp; else if(j>temp) j=temp; } } } } if(j==-1) j=phi; printf("Case #%lld: %lld,%lld\n",++cas,i,j); } return 0; }
相关文章推荐
- POJ 3358- Period of an Infinite Binary Expansion(欧拉函数+欧拉定理)
- POJ 3358 Period of an Infinite Binary Expansion
- poj3358 Period of an Infinite Binary Expansion 数论有难度
- POJ 3358 Period of an Infinite Binary Expansion
- POJ 3358 Period of an Infinite Binary Expansion 欧拉函数+欧拉定理
- poj 3358 Period of an Infinite Binary Expansion
- poj 3358 Period of an Infinite Binary Expansion (费马小定理+分数化二进制小数)
- poj 3358 Period of an Infinite Binary Expansion 欧拉定理
- poj 3358——Period of an Infinite Binary Expansion
- POJ 3358 Period of an Infinite Binary Expansion(欧拉定理)
- Period of an Infinite Binary Expansion POJ - 3358 欧拉函数
- poj 3358 Period of an Infinite Binary Expansion(欧拉函数+欧拉定理)
- poj_3358_Period of an Infinite Binary Expansion
- POJ 3358 Period of an Infinite Binary Expansion
- poj 3358 Period of an Infinite Binary Expansion(数论:欧拉函数+快速幂取模)
- POJ3358 Period of an Infinite Binary Expansion【欧拉函数】
- POJ 3358 Period of an Infinite Binary Expansion ★ (数论好题:欧拉函数)
- POJ 3358 Period of an Infinite Binary Expansion 解题报告(欧拉函数+因式分解)
- POJ 3358 Period of an Infinite Binary Expansion ★ (数论好题:欧拉函数)
- POJ-3358-Period of an Infinite Binary Expansion 解题报告