P2350-[HAOI2012]外星人【线性筛】

正题

题目链接:https://www.luogu.com.cn/problem/P2350


题目大意

给出(N)质因数分解之后的结果,求每次(N=varphi(N)),多少次后(N=1)

(N=prod_{i=1}^mp_i^{q_i},1leq mleq 2000,1leq p_ileq 10^5,1leq q_ileq 10^9)


解题思路

我是傻逼((((

首先(varphi(prod_{i=1}^mp_i^{q_i})=prod_{i=1}^m(p_i-1)p_i^{q_i-1})
开始想太多了,以为传递的延迟影响很大,后来发现设因为(p_i-1)一定是偶数,所以把(p_i-1)分解后一定有(2)这个质因子,所以只有在(N)没有(2)这个质因子的情况下传递的延迟会造成一次的影响,否则都没有影响,因为(2)还没有抵消延迟就已经结束了。

所以我们只需要考虑每个质数能传递出多少个(2),这个用线性筛可以解决因为最后更新一个质数的一定是新增的一个质因子。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10,M=1e5+10;
int T,n,cnt,pri[N],f[M],v[M];
void Prime(){
	f[1]=1;
	for(int i=2;i<M;i++){
		if(!v[i])pri[++cnt]=i,f[i]=f[i-1];
		for(int j=1;j<=cnt&&i*pri[j]<M;j++){
			v[i*pri[j]]=1;
			f[i*pri[j]]=f[i]+f[pri[j]];
			if(i%pri[j]==0)break;
		}
	}
	return;
}
int main()
{
	Prime();
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		if(!n)puts("0");
		long long ans=1;
		for(int i=1;i<=n;i++){
			int x,w;
			scanf("%d%d",&x,&w);
			if(x==2)ans--;
			ans+=1ll*f[x]*w;
		}
		printf("%lld
",ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/QuantAsk/p/14957198.html