E - Sum of gcd of Tuples (Hard)
莫比乌斯反演过程:
最后就是
#include <bits/stdc++.h> using namespace std ; const int mod = 1e9 + 7 ; const int N = 1e5 + 5 ; int phi[N] , tot , prime[N] , vis[N] ; typedef long long ll ; ll qmi(ll a ,ll b) { ll res = 1; while(b) { if(b & 1) res = res * a % mod ; a = a * a % mod ; b >>= 1 ; } return res; } void init() { phi[1] = 1 ; for(int i = 2; i < N ;i ++) { if(!vis[i]) prime[++ tot] = i , phi[i] = i - 1; for(int j = 1 ; j <= tot && i * prime[j] < N ;j ++) { vis[i * prime[j]] = 1; if(i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j] ; break ; } phi[i * prime[j]] = phi[i] * phi[prime[j]] ; } } } int main() { init() ; int n , k ; cin >> n >> k ; long long ans = 0 ; for(int i = 1 ; i <= k ;i ++) ans += qmi(k / i , n) * phi[i] % mod , ans %= mod ; cout << ans << endl ; return 0 ; }
官方做法, 看着像dp , 也是容斥,最小gcd为i , 那么所有i的组合成答案多了很多i的倍数为gcd的,所以后面就剪掉
#include <bits/stdc++.h> using namespace std ; const int mod = 1e9 +7 , N = 1e5 + 5 ; typedef long long ll ; ll dp[N] ; ll qmi(ll a, ll b) { ll res =1 ; while(b) { if(b & 1) res = res * a % mod ; a = a * a % mod ; b >>= 1; } return res ; } int main() { ll ans = 0 ; int n , k ; cin >> n >> k ; for(int i = k ;i >= 1;i --) { dp[i] = qmi(k / i , n) % mod ; for(int j = 2 * i ;j <= k ;j += i) dp[i] -= dp[j] , dp[i] = (dp[i] % mod + mod) % mod ; ans += i * dp[i] % mod , ans %= mod ; } cout << ans << endl ; return 0 ; }