[Codeforces 547C] Mike And Foam 莫比乌斯反演

F(i)=sigma(i|d,f(d))=C(g(i),2),g(i)是现在的i的倍数的数量,f(i)=sigma(i|d,miu(d/i)*F(d))所求即为f(1)的值.动态维护g(i)即可.

Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll ans=0;
int n,q,id;
int miu[500005],pri[100005],cnt=0;
bool isp[500005];
bool vis[200005];
int a[200005];
ll g[500005];
inline void gmiu()
{miu[1]=1;
for (int i=2;i<=500000;i++)
{if (!isp[i]) {pri[++cnt]=i;miu[i]=-1;}
for (int j=1;j<=cnt&&pri[j]*i<=500000;j++)
{isp[i*pri[j]]=1;
if (i%pri[j]==0) {miu[i*pri[j]]=0;break;}
miu[i*pri[j]]=miu[i]*(-1);
}
}
}
void add(int num,int del)
{int i,t;
ll prv,rev;
for (i=1;i*i<=num;i++)
{if (num%i==0)
{t=i;prv=miu[t]*g[t]*(g[t]-1)/2;
g[t]+=del;rev=miu[t]*g[t]*(g[t]-1)/2;
ans-=prv;ans+=rev;
if (i!=num/i)
{t=num/i;prv=miu[t]*g[t]*(g[t]-1)/2;
g[t]+=del;rev=miu[t]*g[t]*(g[t]-1)/2;
ans-=prv;ans+=rev;
}
}
}
printf ("%lld\n",ans);
}
int main (){
	gmiu();
	int i;
	scanf ("%d%d",&n,&q);
	for (i=1;i<=n;i++)
	{scanf ("%d",&a[i]);}
	for (i=1;i<=q;i++)
	{scanf ("%d",&id);
	if (!vis[id]) {vis[id]=1;add(a[id],1);}
	else {vis[id]=0;add(a[id],-1);}
	}
	return 0;
}
	


全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务