首页 > 代码库 > POJ 3696
POJ 3696
这里面的一个转换的小技巧很重要,把888...8转换成(10^x-1)/9*8。神来之笔,佩服。
这样有(10^x-1)/9*8=L*p得10^x-1=L*p*9/8,设m=9*L/gcd(L,8)。这一步如何想到的呢?其实是为了使m与10互质而做的。因为这样必有m*p1=10^x-1。使得同余方程
10^x=1 mod m,相信到了这一步,都知道用欧拉定理了。于是只需求出phi(m),枚举其因子,使得同余方程成立即可
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define LL __int64using namespace std;LL gcd(LL a,LL b){ if(b==0) return a; return gcd(b,a%b);}LL fac[10000]; int cnt;LL Euler(LL m){ LL res=m; LL k=(LL)sqrt((double)m); for(LL i=2;i<=k;i++){ if(m%i==0){ res=res-res/i; while(m%i==0) m/=i; } } if(m>1) res=res-res/m; return res;}LL multi(LL a,LL b,LL m){ LL ret=0; while(b>0){ if(b&1) ret=(ret+a)%m; b>>=1; a=(a<<1)%m; } return ret;}LL quick(LL a,LL k,LL m){ LL ans=1; while(k){ if(k&1) ans=multi(ans,a,m); k=(k>>1); a=multi(a,a,m); } return ans;}int main(){ LL l; int kase=0; while(scanf("%I64d",&l),l){ if(l%16==0||l%5==0) { printf("Case %d: 0\n",++kase); continue; } cnt=0; LL m=l*9/gcd(l,(LL)8); LL phi=Euler(m); LL ans; LL k=(LL)sqrt((double)phi); for(LL i=1;i<=k;i++){ if(phi%i==0){ fac[cnt++]=i; fac[cnt++]=phi/i; } } sort(fac,fac+cnt); for(int i=0;i<cnt;i++){ ans=quick((LL)10,fac[i],m); if(ans==1){ printf("Case %d: %I64d\n",++kase,fac[i]); break; } } } return 0;}
POJ 3696
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。