南京网络赛 18 J Sum 线性筛,素因子分解

题意:定义x为square-free数,当x不被任意一个大于1的平方数整除. (x的素因子幂全都<2).
令f[n]为 n=a*b 并且a,b都为square-free数的方案数. 
n<=2e7 求Σf[i] [i=1:n].


求f[n], n= p1^a1 * p2^a2 *...pk^ak.
此时b选择某些因子,a也就固定了.
a[i]>=3,(那么f[n]==0 因为b最多只能选幂为1)
a[i]==2 那么b一定会选该因子.
a[i]==1 那么b可以选或者不选.
于是总的方案就是 n的素因子分解中,2^素因子幂为1的个数

做线性筛的时候求出幂为1的因子个数即可.

#include <bits/stdc++.h>
using namespace std;
const int N=2e7+5,inf=1e9;
int pri[N],pn=0,d[N],res[N];
bool vis[N];
void init(){
	for(int i=2;i<N;i++){
		if(!vis[i]){
			pri[++pn]=i;
			d[i]=1;
		}
		for(int j=1;j<=pn&&i*pri[j]<N;j++){
			vis[i*pri[j]]=true;
			if(i%pri[j]==0){
				if((i%(pri[j]*pri[j]))==0)	d[i*pri[j]]=-inf;
				else d[i*pri[j]]=d[i]-1;// i*pri[j] = pri[j]^2 *..
				break;
			}
			else d[i*pri[j]]=d[i]+1;
		}
	}
//	for(int i=1;i<=30;i++)	cout<<i<<' '<<d[i]<<'\n';		
	res[1]=1;
	for(int i=2;i<N;i++){
		res[i]=res[i-1];
		if(d[i]<0)	continue;
		res[i]+=(1<<d[i]);
	}
}
int main(){
	init();
	int n,T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		printf("%d\n",res[n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/noone0/article/details/82291649
今日推荐