题目大意
给定一个数n,求∑ni=1∑nj=1ϕ(ϕi,ϕj)
n≤2∗106 数据组数不超过5
分析
//这是我复习莫比乌斯反演的一道练习。。
首先可以考虑枚举gcd的值。首先预处理一个数组s[],s[i]表示n以内正整数中,欧拉函数等于i的有多少个。那么答案变成:
ans=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋ϕd∗s[id]∗s[jd][(i,j)=1]
考虑到这里有(i,j)=1的限制,就可以上反演了。
令g(d)=∑⌊nd⌋i=1∑⌊nd⌋j=1ϕs[id]∗s[jd][(i,j)=1],f(d)=∑⌊nd⌋k=1g(kd),那么:
f(d)=∑i=1⌊nd⌋∑j=1⌊nd⌋ϕs[id]∗s[jd]
f数组可以nlogn预处理,然后:
g(d)=∑i=1⌊nd⌋μi∗f(id)
ans=∑d=1ng(d)∗ϕd=∑d=1nϕd∑i=1⌊nd⌋μi∗f(id)
时间复杂度O(nlogn),但是时限为2s,且n有点大,要注意常数。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2e6+5;
typedef long long LL;
int T,n,tot,p[N],phi[N],mu[N];
LL ans,s[N],f[N];
bool bz[N];
void work()
{
scanf("%d",&n);
ans=tot=0;
memset(bz,0,sizeof(bz));
memset(phi,0,sizeof(phi));
memset(mu,0,sizeof(mu));
memset(s,0,sizeof(s));
memset(f,0,sizeof(f));
mu[1]=phi[1]=1;
for (int i=2;i<=n;i++)
{
if (!bz[i])
{
p[tot++]=i; mu[i]=-1; phi[i]=i-1;
}
for (int j=0;j<tot;j++)
{
int k=i*p[j];
if (k>n) break;
bz[k]=1;
if (i%p[j]==0)
{
mu[k]=0;
phi[k]=phi[i]*p[j];
break;
}
mu[k]=-mu[i];
phi[k]=phi[i]*(p[j]-1);
}
}
for (int i=1;i<=n;i++) s[phi[i]]++;
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j+=i) f[i]+=s[j];
for (int i=1;i<=n;i++) f[i]=f[i]*f[i];
for (int i=1;i<=n;i++) if (mu[i]!=0)
for (int d=1;i*d<=n;d++) ans+=mu[i]*phi[d]*f[i*d];
printf("%lld\n",ans);
}
int main()
{
for (scanf("%d",&T);T--;work());
return 0;
}
这是一道关于复习莫比乌斯反演的数学问题。给定一个数n,目标是计算所有i, j (1 ≤ i, j ≤ n)之间欧拉函数值ϕ(ϕi, ϕj)的和,当i和j的最大公约数为1时。通过预处理欧拉函数的值并应用莫比乌斯反演,可以将问题转化为求解gcd的和,最终达到O(nlogn)的时间复杂度解题。"
125140459,1309789,SpringMVC启动与执行流程及Controller线程安全性解析,"['面试', 'java', 'springmvc']
488

被折叠的 条评论
为什么被折叠?



