小Q与函数求和1
https://ac.nowcoder.com/acm/contest/11171/E
给定 \(N,k\),\(1\le N\le 5\cdot 10^6,-1\le k\le 10^9\),求:
\[\sum_{i=1}^N\sum_{j=1}^N\varphi(ij\gcd(i,j)^k)
\]
2s,512MB。
\[\begin{aligned}
\sum_{i=1}^N\sum_{j=1}^N\varphi(ij\gcd(i,j)^k)&=\sum_{i=1}^N\sum_{j=1}^N\varphi(ij)\gcd(i,j)^k\\
&=\sum_{d=1}^N\sum_{i=1}^N\sum_{j=1}^N[\gcd(i,j)=d]d^k\frac{\varphi(i)\varphi(j)d}{\varphi(d)}\\
&=\sum_{d=1}^N\frac{d^{k+1}}{\varphi(d)}\sum_{i=1}^{\lfloor N/d\rfloor}\sum_{j=1}^{\lfloor N/d\rfloor}[\gcd(i,j)=1]\varphi(id)\varphi(jd)\\
&=\sum_{d=1}^N\frac{d^{k+1}}{\varphi(d)}\sum_{i=1}^{\lfloor N/d\rfloor}\sum_{j=1}^{\lfloor N/d\rfloor}\sum_{x|i\and x|j}\mu(x)\varphi(id)\varphi(jd)\\
&=\sum_{x=1}^N\sum_{d=1}^N\frac{d^{k+1}}{\varphi(d)}\left(\sum_{i=1}^{\lfloor N/d\rfloor}[x|i]\varphi(id)\right)^2\\
&=\sum_{x=1}^N\mu(x)\sum_{d=1}^N\frac{d^{k+1}}{\varphi(d)}\left(\sum_{i=1}^{\lfloor N/dx\rfloor}\varphi(idx)\right)^2\\
&=\sum_{T=1}^N\sum_{x|T}
\mu(x)\frac{\left(\frac{T}{x}\right)^{k+1}}{\varphi\left(\frac{T}{x}\right)}\left(\sum_{i=1}^{\lfloor N/T\rfloor} \varphi(iT)\right)^2\end{aligned}
\]
\(\mu(x)\frac{\left(T/x\right)^{k+1}}{\varphi\left(T/x\right)}\) 和 \(\sum_{i=1}^{\lfloor N/T\rfloor} \varphi(iT)\) 都可以 \(\mathcal O(n\ln n)\) 预处理出,这道题就做完了
下面是被卡常的丑陋代码。题解区代码都被卡常了
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
const int N=5e6+10,mod=998244353;
int pri[N],phi[N],pw[N],cnt,k,n,mu[N],inv[N];
bool vis[N];
int qpow(int a,int n)
{
int ans=1;
while(n)
{
if(n&1)ans=a*ans%mod;
a=a*a%mod;
n>>=1;
}
return ans;
}
void sieve()
{
pw[1]=1,phi[1]=1,mu[1]=1,inv[1]=1;
for(int i=2;i<=n;i++)
{
if(mu[i]==mod)mu[i]=0;
if(!vis[i])pri[++cnt]=i,pw[i]=qpow(i,k+1),phi[i]=i-1,mu[i]=mod-1;
for(int j=1;j<=cnt&&pri[j]*i<=n;j++)
{
int x=i*pri[j];
vis[x]=1;
pw[x]=pw[i]*pw[pri[j]]%mod;
phi[x]=(pri[j]-1)*phi[i];
mu[x]=mod-mu[i];
if(i%pri[j]==0)
{
phi[x]=pri[j]*phi[i];
mu[x]=0;
break;
}
}
}
}
int f[N],g[N];
void Add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
signed main()
{
n=read(),k=read();sieve();
inv[0]=inv[1]=1;for(int i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
int ans=0;
for(int i=1;i<=n;i++)for(int j=1;j*i<=n;j++)
{
int x=i*j;
Add(f[x],mu[i]*pw[j]%mod*inv[phi[j]]%mod),Add(g[i],phi[x]);
}
for(int i=1;i<=n;i++)Add(ans,f[i]*g[i]%mod*g[i]%mod);
printf("%lld\n",ans);
return 0;
}