51Nod1037 最长的循环节 V2


题目看这里
小学奥数题目23333
首先我们知道,0.0˙0...001˙=1/99..9
那么任意一个循环小数都可以写成以10k1为分母的分数
让后稍加分析就知道,满足条件的最小的k就是循环节的长度
那么题目就变成了求一个数s,使得满足10k=1 ( mod s )这样的k最大
我们将k记为f(s)
首先由欧拉定理得10ϕ(s)=1(mod s)所以f(s)|ϕ(s)
让后再根据打表的规律,我们发现满足条件的数其实非常多(密度>0.5)
所以我们可以猜测,只有当f(s)=ϕ(s)时才能取到最多(否则2f(s)<=ϕ(s)
于是我们采用Miller Rabin+Pollard Rho来分解质因数求ϕ,从n开始向 下枚举即可,由于密度很高,所以很快就可以得到答案

#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<time.h>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define LL long long
using namespace std;
vector<LL> s,t,w;
inline LL mul(LL x,LL k,LL M,LL s=0){
for(;k;x=(x+x)%M,k>>=1) k&1?s=(s+x)%M:0;
return s;
}
inline LL pow(LL x,LL k,LL M,LL s=1){
for(;k;x=mul(x,x,M),k>>=1) k&1?s=mul(s,x,M):0;
return s;
}
inline bool test(LL n,LL a,LL d){
if(n==2 || n==a) return 1;
if( n&1) return 0;
while( d&1) d>>=1;
LL t=pow(a,d,n);
while((d!=n1)&&(t!=1)&&(t!=n1)){
t=mul(t,t,n);
d<<=1;
}
return (t==n1 || d&1);
}
inline bool prime(LL n){
if(n<2) return 0;
int a[6]={2,61,3,40357,49919,19260817};
for(int i=0;i<5;++i)
if(!test(n,a[i],n1)) return 0;
return 1;
}
inline LL gcd(LL a,LL b){
for(LL c;b;a=b,b=c) c=a%b;
return a;
}
inline LL rho(LL n){
begin:
LL c=rand()%n; int i=1,k=2;
LL x=rand()%n+1,y=x,d;
for(;;){
i++;
x=(mul(x,x,n)+c)%n;
d=gcd(xy,n);
if(1<d && d<n) return d;
if(y==x) goto begin;
if(i==k){ y=x; k<<=1; }
}
}
inline LL read(){
LL x=0; char c=getchar();
while(c>9 || c<0) c=getchar();
while(c>=0&&c<=9){ x=(x<<3)+(x<<1)+(c48);c=getchar(); }
return x;
}
LL n;
inline void dfs(LL x){
if(prime(x)){ s.push_back(x); return; } 
LL y=rho(x); while(x%y==0) x/=y;
if(x>1) dfs(x); dfs(y);
}
inline void dt(LL x,int i){
if(i==s.size()){ w.push_back(x); return; }
for(int j=0;j<=t[i];++j) dt(x,i+1),x=s[i];
}
int d(LL n){
if(!prime(n)) return 0; LL m=n1;
s.clear(); t.clear(); w.clear(); dfs(n1); 
for(int i=0;i<s.size();++i) 
for(t.push_back(0);m%s[i]==0;m/=s[i]) ++t[i];
dt(1,0);
sort(w.begin(),w.end());
for(int i=0;i<w.size();++i) 
if(pow(10,w[i],n)==1){
if(w[i]==n1){ printf("%lld\n",n); exit( 0 ); }
else return 0;
}
}
int main(){
n=read();
while(!d(n)) n;
}

posted @ 2018-07-28 23:17  扩展的灰(Extended_Ash)  阅读(234)  评论(0编辑  收藏  举报