bzoj3739 DZY loves math VIII 莫比乌斯函数

       智商太低到现在还不会用μ函数做题。。膜拜了Claris的题解(其实主要是去看代码的)。

       显然当gcd(i,j)>0时,对答案是没有贡献的的,因此化简原式得到:

       

       如果令

       我们可以发现f(i,d)=f(i-d,d)+μ(i)。然后可以暴力枚举因数d,最后更新f(i,d)(实际上只需要保存后面一维即可),然后就好了。

AC代码如下:

#include<iostream>
#include<cstdio>
#define N 10000005
using namespace std;

int n,cnt,mu[N],c[1000005],ask[1005],f[N],a[15],p[N],sum[N];
void pfs(){
	int i,j,k; mu[1]=1;
	for (i=2; i<=n; i++){
		if (!p[i]){ p[i]=c[++c[0]]=i; mu[i]=-1; }
		for (j=1; j<=c[0] && (k=i*c[j])<=n; j++){
			p[k]=c[j];
			if (i%c[j]) mu[k]=-mu[i];
				else{ mu[k]=0; break; }
		}
	}
}
int dfs(int k,int x,int v){
	if (k>cnt){
		f[x]+=v; return mu[x]*f[x];
	}
	return dfs(k+1,x*a[k],v)+dfs(k+1,x,v);
}
int main(){
	int cas,i; scanf("%d",&cas);
	for (i=1; i<=cas; i++){
		scanf("%d",&ask[i]); n=max(n,ask[i]);
	}
	pfs();
	for (i=1; i<=n; i++){
		sum[i]+=sum[i-1];
		if (mu[i]){
			cnt=0; int x=i;
			for (; x>1; x/=p[x]) a[++cnt]=p[x];
			sum[i]+=mu[i]*dfs(1,1,mu[i]);
		}
	}
	for (i=1; i<=cas; i++) printf("%d\n",sum[ask[i]]);
	return 0;
}


by lych

2016.2.23

你可能感兴趣的:(数论,DFS,莫比乌斯函数)