题目链接
题解
容易发现本题是 GCD SUM 的推广。
方法一
走莫比乌斯反演的路子,套路性的枚举 \(\gcd\) 的值。
$$ \begin{align} &\sum_{i_1=1}^{m}\sum_{i_2=1}^{m} \ldots \sum_{i_n=1}^{m}\gcd(i_1,i_2, \ldots i_n) \\ =&\sum_{d=1}^{m}d\sum_{i_1=1}^{m}\sum_{i_2=1}^{m} \ldots \sum_{i_n=1}^{m}[\gcd(i_1,i_2, \ldots i_n)=d] \\ =&\sum_{d=1}^{m}d\sum_{i_1=1}^{\lfloor \frac{m}{d} \rfloor}\sum_{i_2=1}^{\lfloor \frac{m}{d} \rfloor} \ldots \sum_{i_n=1}^{\lfloor \frac{m}{d} \rfloor}[\gcd(i_1,i_2, \ldots i_n)=1] \\ =&\sum_{d=1}^{m}d\sum_{i_1=1}^{\lfloor \frac{m}{d} \rfloor}\sum_{i_2=1}^{\lfloor \frac{m}{d} \rfloor} \ldots \sum_{i_n=1}^{\lfloor \frac{m}{d} \rfloor}\sum_{t \mid i_1, t \mid i_2, \ldots , t \mid i_n}\mu(t) \\ =&\sum_{d=1}^{m}d\sum_{t=1}^{\lfloor \frac{m}{d} \rfloor}\mu(t)\lfloor \frac{m}{dt} \rfloor^n \\ =&\sum_{T=1}^{m}\lfloor \frac{m}{T} \rfloor ^n \sum_{d|T} d \mu(\frac{T}{d}) \\ =&\sum_{T=1}^{m}\lfloor \frac{m}{T} \rfloor ^n \varphi(T) \end{align} $$
看着挺烦人的,接下来我们有种更简单的方法。
方法二
根据 \(\sum_{d \mid n}\varphi(d)=n\) 的性质直接换掉 \(\gcd\)。
$$ \begin{align} &\sum_{i_1=1}^{m}\sum_{i_2=1}^{m} \ldots \sum_{i_n=1}^{m}\gcd(i_1,i_2, \ldots i_n) \\ =& \sum_{i_1=1}^{m}\sum_{i_2=1}^{m} \ldots \sum_{i_n=1}^{m} \sum_{d \mid \gcd(i_1,i_2, \ldots i_n)}\varphi(d)\\ =& \sum_{d=1}^m \varphi(d)\sum_{i_1=1}^m[d \mid i_1]\sum_{i_2=1}^m[d \mid i_2] \ldots \sum_{i_n=1}^m[d \mid i_n]\\ =& \sum_{d=1}^m \varphi(d)\left \lfloor \frac{m}{d} \right \rfloor^n \end{align}$$
同样的结果,这个方法就比上面简洁多了。
最后直接用杜教筛计算即可。
#include <iostream> #include <algorithm> #include <unordered_map> #define N 20000000 using namespace std; typedef unsigned long long ull; ull phi[N+5]; int pri[N+5],cnt; bool vis[N+5]; unordered_map<ull,ull> psum; ull fpow(ull x,ull y) { ull ans=1; while(y) { if(y&1)ans=ans*x; x=x*x; y>>=1; } return ans; } ull phi_sum(ull x) { if(x<=N)return phi[x]; if(psum.count(x))return psum[x]; ull res=(x&1)?(x+1)/2*x:x/2*(x+1); for(ull l=2,r;l<=x;l=r+1) { r=x/(x/l); res-=(r-l+1)*phi_sum(x/l); } return psum[x]=res; } int main() { ull n,m,ans=0; cin>>n>>m; phi[1]=1; for(int i=2;i<=N;i++) { if(!vis[i])phi[i]=i-1,pri[++cnt]=i; for(int j=1;j<=cnt&&i*pri[j]<=N;j++) { vis[i*pri[j]]=1; if(i%pri[j]!=0) phi[i*pri[j]]=phi[i]*phi[pri[j]]; else { phi[i*pri[j]]=phi[i]*pri[j]; break; } } } for(int i=1;i<=N;i++) phi[i]+=phi[i-1]; for(ull l=1,r;l<=m;l=r+1) { r=m/(m/l); ans+=fpow(m/l,n)*(phi_sum(r)-phi_sum(l-1)); } cout<<ans<<endl; return 0; }