1. 程式人生 > >51nod1237 最大公約數之和 V3

51nod1237 最大公約數之和 V3

const clas 轉化 .com pre long cli play opened

題意:求

技術分享圖片

解:

技術分享圖片

最後一步轉化是因為phi * I = Id,故Id * miu = phi

第二步是反演,中間省略了幾步...

然後就這樣A了......最終式子是個整除分塊,後面用杜教篩求一下phi前綴和即可。

技術分享圖片
 1 #include <cstdio>
 2 #include <map>
 3 
 4 typedef long long LL;
 5 const int N = 5000010, T = 5000008;
 6 const LL MO = 1000000007;
 7 
 8 int p[N], top, phi[N];
 9 LL Phi[N], inv2;
10 bool vis[N]; 11 std::map<LL, LL> mp; 12 13 inline void getp(int n) { 14 phi[1] = 1; 15 for(int i = 2; i <= n; i++) { 16 if(!vis[i]) { 17 p[++top] = i; 18 phi[i] = i - 1; 19 } 20 for(int j = 1; j <= top && i * p[j] <= n; j++) {
21 vis[i * p[j]] = 1; 22 if(i % p[j] == 0) { 23 phi[i * p[j]] = phi[i] * p[j]; 24 break; 25 } 26 phi[i * p[j]] = phi[i] * (p[j] - 1); 27 } 28 } 29 for(int i = 1; i <= n; i++) { 30 Phi[i] = (Phi[i - 1
] + phi[i]) % MO; 31 } 32 return; 33 } 34 35 LL getPhi(LL x) { 36 if(x <= 0) return 0; 37 if(x <= T) return Phi[x]; 38 if(mp.count(x)) return mp[x]; 39 LL ans = (x + 1) % MO * (x % MO) % MO * inv2 % MO; 40 for(LL i = 2, j; i <= x; i = j + 1) { 41 j = x / (x / i); 42 ans -= (j - i + 1) % MO * getPhi(x / i) % MO; 43 ans %= MO; 44 } 45 return mp[x] = (ans + MO) % MO; 46 } 47 48 int main() { 49 LL n; 50 getp(T); 51 inv2 = (MO + 1) / 2; 52 scanf("%lld", &n); 53 LL ans = 0; 54 for(LL i = 1, j; i <= n; i = j + 1) { 55 j = n / (n / i); 56 LL temp = (n / i) % MO; 57 ans += temp * temp % MO * (getPhi(j) - getPhi(i - 1) + MO) % MO; 58 ans %= MO; 59 } 60 printf("%lld\n", (ans + MO) % MO); 61 return 0; 62 }
AC代碼

51nod1237 最大公約數之和 V3