[HDU2462] The Luckiest number
阿新 • • 發佈:2020-09-03
前言
差一點就推出來了qaq
題目
題目大意:
多組詢問,0結束,問\(x=88...888\)(len個\(8\)),且\(L|x\)的最小\(len\),如果無解輸出\(0\)
輸出格式見樣例
講解
首先我們可以將\(x\)表示為\((10^{len}-1)/9*8\)
那麼\(L|(10^{len}-1)/9*8\),\(L*9|(10^{len}-1)*8\)
令\(d=gcd(L*9,8)\),所以\(L*9/d|(10^{len}-1)*8/d\)
令\(L'=L*9/d\),因為\(L*9/d\)與\(8/d\)互質,所以\(L'|(10^{len}-1)\)
那麼一定可以寫成這種形式:\(10^{len}\% L'=1\)
此時如果\(10\)與\(L'\)不互質,一定無解
否則\(10^{\phi(L')}\% L'=1\),\(\phi(L')\)即為答案
嗎?
我們要求最小的答案,所以我們只需列舉\(\phi(L')\)的因數,再用快速冪判斷即可
值得注意的是在快速冪期間,中間變數可能會爆\(long\ long\),所以要使用防爆乘法
程式碼
LL gcd(LL x,LL y) { if(!y) return x; return gcd(y,x%y); } LL getphi(LL x) { LL ret = x; for(int i = 2;1ll * i * i <= x;++ i) { if(x % i == 0) { ret = ret / i * (i-1); while(x % i == 0) x /= i; } } if(x > 1) ret = ret / x * (x-1); return ret; } LL gsc(LL x,LL y,LL MOD) { LL ret = 0; while(y){if(y & 1) ret = (ret + x) % MOD;x = (x << 1) % MOD;y >>= 1;} return ret; } LL qpow(LL x,LL y,LL MOD) { LL ret = 1; while(y){if(y & 1) ret = gsc(ret,x,MOD);x = gsc(x,x,MOD);y >>= 1;} return ret; } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); while(1) { n = Read(); if(!n) return 0; n *= 9; LL d = gcd(n,8),ans,phi; n /= d; if(gcd(n,10) > 1) {printf("Case %d: 0\n",++tot);continue;} ans = phi = getphi(n); for(int i = 1;1ll*i*i <= phi;++ i) if(phi % i == 0) { if(qpow(10,i,n) == 1) {ans = i;break;} if(qpow(10,phi/i,n) == 1) ans = phi/i; } printf("Case %d: %lld\n",++tot,ans); } return 0; }