另一種容斥做法
反演做法(複習一下反演)
n個求和
∑i=1k∑j=1k...∑z=1kgcd(i,j...z)
做個變換 ∑x=1kx∑i=1k∑j=1k...∑z=1k[gcd(i,j...z)=x]
設f(x)=∑i=1k∑j=1k...∑z=1k[gcd(i,j...z)=x]
設g(x)=∑x∣df(d)=∑x∣d∑i=1k∑j=1k...∑z=1k[gcd(i,j...z)=d]
= [(int)(xk)]n gcd(i,j,…z)爲x的倍數,每個位置取值(int)(xk)個
反演一手 f(x)=∑x∣du(xd)g(d)=∑x∣du(xd)[(int)(xk)]n
原式就=∑x=1kx∑x∣du(xd)[(int)(dk)]n
令T=xd ,d=T∗x
= ∑x=1kx∑Tu(T)[(int)(T∗xk)]n
令D=x∗T
= ∑D=1k[(int)(T∗xk)]n∑T∣Du(T)∗TD
= ∑D=1k[(int)(Dk)]nphi(D)
然後分塊+預處理phi前綴和
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
typedef long long ll;
const ll mod = 1e9+7;
bool vis[man];
int prime[man],phi[man];
void init(int maxn){
phi[1] = 1;
vis[1] = 1;
int cnt = 0;
for(int i = 2;i <= maxn;i++){
if(!vis[i]){
prime[cnt++] = i;
phi[i] = i-1;
}
for(int j = 0;j < cnt && i * prime[j] <= maxn;j++){
vis[i*prime[j]] = 1;
phi[i*prime[j]] = phi[i]*phi[prime[j]];
if(i%prime[j]==0){
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
}
}
for(int i = 1;i <= maxn;i++){
phi[i] = (phi[i-1] + phi[i])%mod;
}
}
ll quick_mod(ll a,ll b){
ll ans = 1;
while(b){
if(b&1)ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
#endif
int n,k;
cin >> n >> k;
init(k+5);
ll ans = 0;
for(int l = 1,r = 0;l <= k;l = r + 1){
r = k / (k / l);
ans = (ans + quick_mod(k/l,n)*(phi[r] - phi[l-1] + mod)%mod) % mod;
}
cout << ans << endl;
return 0;
}