51_1037最长循环节 (miller rabin算法 pollard rho算法 原根)
基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
收藏
关注
正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求<=n的数中,倒数循环节长度最长的那个数。
1/6= 0.1(6) 循环节长度为1
1/7= 0.(142857) 循环节长度为6
1/9= 0.(1) 循环节长度为1
Input
输入n(10 <= n <= 10^18)
Output
输出<=n的数中倒数循环节长度最长的那个数
Input示例
10
Output示例
7
主要用到了两个算法:miller rabin算法 pollard rho算法, 前者是种带概率性的判断质数,适用于较大数字的判断(概率性的), 后者用于大数的因式分解
模板代码:
#include <stdlib.h> #include <string.h> #include <algorithm> #include <iostream> #include <math.h> const int Times=10; const int N=5500; using namespace std; typedef long long LL; LL ct,cnt,c,x,y; LL fac[N],num[N],arr[N]; LL gcd(LL a,LL b) { return b? gcd(b,a%b):a; } LL multi(LL a,LL b,LL m) { LL ans=0; while(b) { if(b&1) { ans=(ans+a)%m; b--; } b>>=1; a=(a+a)%m; } return ans; } LL quick_mod(LL a,LL b,LL m) { LL ans=1; a%=m; while(b) { if(b&1) { ans=multi(ans,a,m); b--; } b>>=1; a=multi(a,a,m); } return ans; } bool Miller_Rabin(LL n) { if(n==2) return true; if(n<2||!(n&1)) return false; LL a,m=n-1,x,y; int k=0; while((m&1)==0) { k++; m>>=1; } for(int i=0; i<Times; i++) { a=rand()%(n-1)+1; x=quick_mod(a,m,n); for(int j=0; j<k; j++) { y=multi(x,x,n); if(y==1&&x!=1&&x!=n-1) return false; x=y; } if(y!=1) return false; } return true; } LL Pollard_rho(LL n,LL c) { LL x,y,d,i=1,k=2; y=x=rand()%(n-1)+1; while(true) { i++; x=(multi(x,x,n)+c)%n; d=gcd((y-x+n)%n,n); if(1<d&&d<n) return d; if(y==x) return n; if(i==k) { y=x; k<<=1; } } } void find(LL n,int c) { if(n==1) return; if(Miller_Rabin(n)) { fac[ct++]=n; return ; } LL p=n; LL k=c; while(p>=n) p=Pollard_rho(p,c--); find(p,k); find(n/p,k); } void dfs(LL dept, LL product=1) { if(dept==cnt) { arr[c++]=product; return; } for(int i=0; i<=num[dept]; i++) { dfs(dept+1,product); product*=fac[dept]; } } void Solve(LL n) { ct=0; find(n,120); sort(fac,fac+ct); num[0]=1; int k=1; for(int i=1; i<ct; i++) { if(fac[i]==fac[i-1]) ++num[k-1]; else { num[k]=1; fac[k++]=fac[i]; } } cnt=k; } const int M=1000005; bool prime[M]; int p[M]; int k1; void isprime() { k1=0; int i,j; memset(prime,true,sizeof(prime)); for(i=2;i<M;i++) { if(prime[i]) { p[k1++]=i; for(j=i+i;j<M;j+=i) { prime[j]=false; } } } } int main() { LL n,t,record,tmp; isprime(); while(cin>>n) { LL ans=-1; record=0; while(true) { tmp=1; if(Miller_Rabin(n)) { Solve(n-1); c=0; dfs(0,1); sort(arr,arr+c); bool flag=0; for(int i=0; i<c; i++) { if(quick_mod(10,arr[i],n)==1) { tmp=arr[i]; break; } if(i==c-2) flag=1; } if(flag) { if(ans<tmp) record=n; cout<<record<<endl; break; } } else { bool flag=false; LL tmp1=(LL)sqrt(n*1.0); if(tmp1*tmp1==n&&Miller_Rabin(tmp1)) { x=tmp1; y=2; flag=true; } else { LL cnt1=0,rea=n; for(int i=0;i<k1;i++) { if(rea%p[i]==0) { x=p[i]; while(rea%p[i]==0) { rea/=p[i]; cnt1++; } break; } } if(rea==1) flag=true; y=cnt1; } if(flag) { Solve(x-1); c=0; dfs(0,1); sort(arr,arr+c); bool flag=0; for(int i=0; i<c; i++) { if(quick_mod(10,arr[i],x)==1) { tmp=1; for(int j=0; j<y-1; j++) tmp*=x; tmp*=(x-1); break; } if(i==c-2) flag=1; } if(flag) { if(ans<tmp) { ans=tmp; record=n; } } } } n--; } } return 0; }