【poj3358】消因子+BSGS 或 消因子+欧拉定理 两种方法
2016-06-23 17:21
597 查看
题意:给你一个分数,求它在二进制下的循环节的长度,还有第一个循环节从哪一位开始。
For example, x = 1/10 = 0.0001100110011(00110011)w and 0001100110011 is a preperiod and 00110011 is a period of 1/10.
思路一:
就是求p*(2^i) == p*(2^j) (mod q),除过来就是2^(i-j)==1(mod q)
思路二:转自http://www.cnblogs.com/Konjakmoyu/p/5183339.html
实现方法:
方法一: 直接BSGS
求2^x==1(mod n),就先消因子,然后在BSGS求解。
过程中如果b%d!=0,那就说明在x>=T时无解。
方法二:欧拉定理
先消因子,则2与n互质。
求2^x==1(mod n),根据欧拉定理2^phi(n)==1(%n),然后找phi(n)的质因子k。
从小到大枚举质因子k,判断2^k==1(%n)则的得到答案。
代码
BSGS的:
欧拉定理的:
For example, x = 1/10 = 0.0001100110011(00110011)w and 0001100110011 is a preperiod and 00110011 is a period of 1/10.
思路一:
我们可以观察一下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'')
就是求p*(2^i) == p*(2^j) (mod q),除过来就是2^(i-j)==1(mod q)
思路二:转自http://www.cnblogs.com/Konjakmoyu/p/5183339.html
实现方法:
方法一: 直接BSGS
求2^x==1(mod n),就先消因子,然后在BSGS求解。
过程中如果b%d!=0,那就说明在x>=T时无解。
方法二:欧拉定理
先消因子,则2与n互质。
求2^x==1(mod n),根据欧拉定理2^phi(n)==1(%n),然后找phi(n)的质因子k。
从小到大枚举质因子k,判断2^k==1(%n)则的得到答案。
代码
BSGS的:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; const LL N=40000; LL pl,bl; LL p ; bool vis ; struct node{ LL d,id; }bit ; bool cmp(node x,node y){ if(x.d==y.d) return x.id<y.id; return x.d<y.d; } LL exgcd(LL a,LL b,LL &x,LL &y) { if(b==0) {x=1,y=0;return a;} LL tx,ty; LL d=exgcd(b,a%b,tx,ty); x=ty;y=tx-(a/b)*ty; return d; } LL find(LL x) { int l=1,r=bl; while(l<=r) { int mid=(l+r)>>1; if(bit[mid].d==x) return bit[mid].id; if(bit[mid].d<x) l=mid+1; if(bit[mid].d>x) r=mid-1; } return -1; } void exBSGS(LL b,LL &xx,LL &yy) { LL t,m,g,x,y,pm,am; while(b%2==0) {b/=2;xx++;} t=2; for(int i=1;i<=100;i++) { if(t%b==1) {yy=i;return ;} t=t*2%b; } m=(LL)(ceil((double)sqrt((double)b))); pm=1%b;bit[0].d=1%b;bit[0].id=0; for(int i=1;i<=m;i++) { bit[i].d=bit[i-1].d*2%b; bit[i].id=i; pm=pm*2%b; } sort(bit+1,bit+1+m,cmp); bl=1; for(int i=2;i<=m;i++) { if(bit[i].d!=bit[bl].d) bit[++bl]=bit[i]; } exgcd(pm,b,x,y); am=x%b+b; t=1%b; for(int i=0;i<=m;i++) { x=find(t); if(x!=-1) {yy=i*m+x;return ;} t=t*am%b; } return ; } int main() { freopen("a.in","r",stdin); freopen("b.out","w",stdout); LL T=0,a,b; char c; while(scanf("%I64d%c%I64d",&a,&c,&b)!=EOF) { LL x,y; LL g=exgcd(a,b,x,y); a/=g,b/=g; x=1,y=-1; exBSGS(b,x,y); printf("Case #%I64d: %I64d,%I64d \n",++T,x,y); } return 0; }
欧拉定理的:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; const LL Max=(LL)1e6; const LL N=Max+100; LL fl; LL f ; LL gcd(LL a,LL b) { if(b==0) return a; return gcd(b,a%b); } bool cmp(int x,int y){return x<y;} LL eular(LL x) { LL ans=x; for(int i=2;i*i<=x;i++) { if(x%i==0) ans/=i,ans=ans*(i-1); while(x%i==0) x/=i; } if(x>1) ans/=x,ans=ans*(x-1); return ans; } LL quickpow(LL a,LL b,LL mod) { LL ans=1%mod; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } void solve(LL b,LL &xx,LL &yy) { LL k=2,x=b,ans=x; while(b%2==0) xx++,b/=2; LL phi=eular(b); for(int i=1;i*i<=phi;i++) { if(phi%i==0) f[++fl]=i,f[++fl]=phi/i; } sort(f+1,f+1+fl,cmp); for(int i=1;i<=fl;i++) { if(quickpow(2,f[i],b)==1) {yy=f[i];return ;} } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); LL T=0,a,b; char c; while(scanf("%I64d%c%I64d",&a,&c,&b)!=EOF) { LL x=1,y=0; LL g=gcd(a,b); a/=g,b/=g; solve(b,x,y); printf("Case #%I64d: %I64d,%I64d \n",++T,x,y); } return 0; }
相关文章推荐
- 全局变量的初始化顺序
- WebRTC源代码探索之旅——多线程篇-2
- 通过Android Studio查看SDK源码
- 最小路径覆盖_zoj1525_最小路径覆盖+水
- Java解析xml文件
- 模式识别(Pattern Recognition)学习笔记(三十五)-- K-L变换与PCA
- 谷歌浏览器Chrome安装,报0x80004002 等错误时,乖乖的这么解决!亲测有效。
- IntelliJ IDEA 2016.1 创建Maven Java Web项目(图解)
- Windows下通过Composer安装Yii2 [ 2.0 版本 ]
- Java解析xml文件
- +=与=..+..的区别(转自http://www.ticmy.com/?p=285)
- checkbox获取值
- QT中QWidget、QDialog与QMainWindow的区别
- MD5加密工具类
- WebRTC源代码探索之旅——多线程篇-1
- MBX_Main()
- 对象
- PHP微信开发之查询微信精选文章
- 可以看看的 博客
- [从头读历史] 第265节 诗经 周南