另一种容斥做法
反演做法(复习一下反演)
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;
}