[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;
}
	


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值