P2350 [HAOI2012] 外星人 题解

很巧妙的一道题。

首先会发现如果最终 \(\varphi(N)=1\) 的话一定是通过很多次从 \(2\) 这个因子变到 \(1\) 的。而这个函数每迭代一次,就会有且仅有一个 \(2\) 的因子变为 \(1\)。所以题目转化为了求 \(N\) 在函数迭代过程中一共会产生多少个 \(2\) 的因子。

考虑 \(\text{dp}\),设 \(dp_i\) 表示 \(i\) 这个数一共会产生多少个 \(2\)

\(i\) 是质数,那么 \(dp_i=dp_{i-1}\)(一次迭代)。否则 \(dp_{i}=dp_{p}\times dp_{\frac{i}{p}}\)(分成两次算)。所有数的 \(dp\) 的值可以用线性筛 \(O(V)\) 求出。

注意如果 \(N\) 是奇数的话第一次迭代的时候不会有 \(2\) 变为 \(1\),答案要加一。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int MAXN = 1e5 + 10;
int T,n,p,q,dp[MAXN],prime[MAXN],cnt;
bool Not_prime[MAXN];
inline void Get_prime(int n)
{
	for(int i = 2;i <= n;i++)
	{
		if(!Not_prime[i]) prime[++cnt] = i,dp[i] = dp[i - 1];
		if(i == 2) dp[i] = 1;
		for(int j = 1;prime[j] * i <= n;j++)
		{
			Not_prime[prime[j] * i] = 1;
			dp[prime[j] * i] = dp[prime[j]] + dp[i];
			if(i % prime[j] == 0) break;
		}
	}
}
signed main()
{
	Get_prime(100000),cin >> T;
	while(T--)
	{
		cin >> n;int ans = 0;
		for(int i = 1;i <= n;i++) 
		{
			cin >> p >> q;
			ans += dp[p] * q - (p == 2);
		}
		cout << ans + 1 << endl; 
	}
	return 0;
} 
posted @ 2024-02-27 16:44  Creeper_l  阅读(2)  评论(0编辑  收藏  举报