很巧妙的一道题。
首先会发现如果最终 \(\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;
}
标签:prime,迭代,int,题解,P2350,MAXN,HAOI2012,dp
From: https://www.cnblogs.com/Creeperl/p/18037218