P2350

P2350 [HAOI2012]外星人

给定一个表示为 \(\prod_{i=1}^m p_i^{q_i}\) 的数 \(N\)
对于 \(N\),求出 \(x\) 满足 \(\begin{matrix}\underbrace{\varphi(\varphi(\varphi(\varphi(\dots \varphi(N) \dots))))}\\x 个 \varphi()\end{matrix}=1\)

根据题目中给出的提示: $$\varphi\left( \prod_{i=1}^m p_i^{q_i} \right) = \prod_{i=1}^m \left( p_i - 1 \right) \times p_i^{q_i-1} $$
用语言表述就是:对于每次 \(\varphi(N)\) 的操作,相当于将 \(N\) 先除以其每一个质因数,再乘以每个质因数减一的值最后得到的结果。
因为每次只能将质因数减一,所以最后使得乘积为 1 的情况就是质因数 2 减一得到 1,而每次只能将一个 2 转化。
所以最终的操作次数就是每个质因数能拆出 2 的个数(也就是对于一个数,如果是奇数就减一,如果是偶数就分解质因数,最后会有多少个 2)。
考虑进行 DP 预处理。
\(f_i\) 表示的是 \(i\) 能拆出 2 的个数。
则有状态转移方程式:\(\begin{cases}f_i=f_{i-1} \left(\gcd(i,j)=1 \right) \\ f_{x \times y}=f_x+f_y \end{cases}\)
最后有一个细节点:如果一开始给出的质因数中没有 2,则需要进行一次操作之后才能分解出 2,此时要把最后的答案加一。

#include <bits/stdc++.h>
using namespace std;int rd(){
	int w=0,v=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')v=-1;c=getchar();}
	while(c>='0'&&c<='9'){w=(w<<1)+(w<<3)+(c&15);c=getchar();}return w*v;
}const int N=1e5+5e4;int f[N],p[N],flag,T,n,tp,ans;bool is[N];
int main(){
	f[1]=1;for(int i=2;i<=100000;i++){
		if(!is[i])p[++tp]=i,f[i]=f[i-1];
		for(int j=1;j<=tp&&i*p[j]<=100000;j++){is[i*p[j]]=1,f[i*p[j]]=f[i]+f[p[j]];if(i==p[j])break;}
	}T=rd();while(T--){
		n=rd();ans=flag=0;for(int i=1,a,b;i<=n;i++){a=rd(),b=rd();if(a==2)flag=1;ans+=f[a]*b;}
		if(!flag)ans++;cout<<ans<<endl;
	}return 0;
}
posted @ 2022-05-09 13:22  AIskeleton  阅读(41)  评论(0编辑  收藏  举报