[BZOJ2671] Calc和与积 - 容斥原理,莫比乌斯反演定理

本蒟蒻的题解

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
#define regi register int
const int N=50005;int pri[N],cnt,mu[N],n;bool f[N];
void Linear_Shaker(){
	f[1]=true;mu[1]=1;
	for(regi i=2;i<=N-5;i++){
		if(!f[i])pri[++cnt]=i,mu[i]=-1;
		for(regi j=1;j<=cnt&&i*pri[j]<=N;j++){
			f[i*pri[j]]=1,mu[i*pri[j]]=-mu[i];
			if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
		}
	}
}
int di[N<<1],di2[N<<1],top,top2;
ll Calc(){
	ll res=0;
	for(regi y=1;y<=n/(y+1);y++){
		top=0;
		for(regi i=1;i<=y/i;i++){
			if(i*i==y)di[++top]=i;
			else if(y%i==0){
				di[++top]=i;
				di2[++top2]=y/i;
			}
		}
		while(top2)di[++top]=di2[top2--];
		int last=0;
		for(regi x=1;x<y&&x+y<=n/y;x=last+1){
			last=min(n/(n/y/(x+y))/y-y,y-1);
			ll cnt=0;
			for(regi j=1;di[j]<=last&&j<=top;j++)
				cnt+=mu[di[j]]*(last/di[j]-(x-1)/di[j]);
			res+=n/y/(x+y)*cnt;
		}
	}
	return res;
}
int main(){
	Linear_Shaker();cin>>n;
	cout<<Calc()<<endl;
	return 0; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值