poj3696 The Luckiest number(質數,歐拉函數)
阿新 • • 發佈:2019-03-09
所有 ax1 str num stream 約數 main 滿足 href 所以我們可以求出\(phi(9L/d)\)
poj
題意:給定一個正整數L(\(L<=2*10^9\)),求至少多少個8連在一起組成的正整數是L的倍數?
分析:x個8連在一起的正整數可寫作\(8*(10^x-1)/9\),於是題目轉換為了求一個最小的x,使得\(L|8*(10^x-1)/9\),整理一下式子得\(9*L|8*(10^x-1)\),設\(d=gcd(9*L,8)\).
所以有\(9L/d\)與8/d互質,所以式子等價於\((9L/d)|10^x-1\),所以\(10^x≡1(mod(9L/d))\)
若正整數a,n互質,則滿足\(a^x≡1(mod(m))\)的最小正整數\(x\)是\(phi(n)\)的約數.(證明略)
所以我們可以求出\(phi(9L/d)\) ,枚舉它的所有約數,用快速冪判斷是否滿足條件.
#include<iostream> #include<cstdio> #include<cmath> #define ll long long using namespace std; ll gcd(ll a,ll b){ if(b==0)return a; return gcd(b,a%b); } ll quickmul(ll a,ll b,ll c){ ll cnt=0; while(b){ if(b&1)cnt=(cnt+a)%c; a=(a+a)%c; b>>=1; } return cnt; }//快速乘,好像沒什麽必要 ll power(ll a,ll b,ll c){ ll cnt=1; while(b){ if(b&1)cnt=quickmul(cnt,a,c)%c; a=quickmul(a,a,c)%c; b>>=1; } return cnt; } ll get_phi(ll n){ ll cnt=n; for(ll i=2;i*i<=n;++i){ if(n%i==0)cnt=cnt/i*(i-1); while(n%i==0)n/=i; } if(n!=1)cnt=cnt/n*(n-1); return cnt; } int main(){ ll L,T=0; while(scanf("%lld",&L)&&L!=0){ ++T; ll n=9*L/gcd(1ll*8,1ll*9*L);ll x=get_phi(n); if(gcd(10,n)!=1){printf("Case %d: 0\n",T);continue;} int bj=0; for(ll i=1;i*i<=x;i++) if(x%i==0&&power(10,i,n)==1){ printf("Case %lld: %lld\n",T,i); bj=1;break; } if(bj)continue; for(ll i=sqrt(1.0*x);i>=1;i--) if(x%i==0&&power(10,x/i,n)==1){ printf("Case %lld: %lld\n",T,x/i); break; } } return 0; }
poj3696 The Luckiest number(質數,歐拉函數)