hdu 2462(數論:尤拉定理+快速冪取模優化+尤拉函式)
阿新 • • 發佈:2019-02-05
給定一個數,判斷是否存在一個全由8組成的數為這個數的倍數
若存在則輸出這個數的長度,否則輸出0
寫了好久實在想不出來,對著別人的題解才把題目做出來...
通過這個題學會了快速冪,但是程式碼中說的乘法轉化還是看不懂...
百度了一下才知道這個題目是區預賽的題,看來自己和別人還有很多差距啊
------------------------------------------------------------------------------------------------------------------------------
首先,由題意可以得出,(10^x - 1)/ 9 * 8 = L * p(p是一個未知數,但必定是整數)。
然後對上式進行移項處理,得:(10^x - 1) = 9 * L * p / 8。
設m = 9 * L / gcd(L, 8),則有(10^x - 1) = m * p'。p’是必然存在的一個整數。
然後問題就轉化成為了 10^x = 1(mod m),觀察此式,顯然,m和10必定互質。
於是根據尤拉定理,10^(Euler(m)) = 1(mod m) 。由於題目要求最小的解,解必然是Euler(m)的因子。
需要注意的是,對於10^x,由於m太大,直接快速冪相乘的時候會超long long。。。。好bug,需要乘法轉化一下。
程式碼如下:
#include <vector> #include <cstdio> #include <iostream> #include <algorithm> #define LL long long #define MAXN 400010 using namespace std; bool vis[MAXN]; vector<LL> hav; vector<int> prime; LL gcd(LL a, LL b) { return b==0 ? a : gcd(b, a%b); } void gen_primes() { for(int i=2; i<MAXN; ++i) { if(!vis[i]) { prime.push_back(i); if(i < 1111) { for(int j=i*i; j<MAXN; j+=i) { vis[j] = true; } } } } return ; } LL euler_phi(LL n) { LL ans = n; for(int i=0; (LL)(prime[i]*prime[i])<=n; ++i) { if(n%prime[i] == 0) { ans = ans/prime[i]*(prime[i]-1); n /= prime[i]; while(n%prime[i] == 0) n /= prime[i]; } } if(n > 1) { ans = ans/n*(n-1); } return ans; } LL Mul(LL a, LL b, LL c) { LL ans = 0; while(b) { if(b & 1) ans = (ans+a)%c; a = a*2%c; b >>= 1; } return ans; } LL Pow(LL a, LL b, LL c) { LL ans = 1; while(b) { if(b & 1) ans = Mul(ans, a, c); a = Mul(a, a, c); b >>= 1; } return ans; } void get_hav(LL n) { hav.clear(); for(int i=0; i<prime.size()&&n>1; ++i) { while(n%(LL)prime[i] == 0) { n /= prime[i]; hav.push_back(prime[i]); } } if(n > 1) hav.push_back(n); } int main(void) { LL n, m, x, cas = 1; gen_primes(); while(cin >> n && n) { m = 9*n/gcd(n, 8LL); if(gcd(m, 10LL) != 1) { cout << "Case " << cas++ << ": 0" << endl; continue; } x = euler_phi(m); get_hav(x); for(int i=0; i<hav.size(); ++i) { if(Pow(10LL, x/hav[i], m) == 1) x /= hav[i]; } cout << "Case " << cas++ << ": " << x << endl; } return 0; }