「luogu2350」[HAOI2012] 外星人
(Description):
以质数次幂的形式给出一个整数 (N ( N = prod p_i ^ {c_i} , p_i leq 10 ^ 5 c_i leq 10 ^ 9)),求进行几次 (N = varphi(N)) 后可以变成 (1)。
(Solution):
[varphi(N) = N prod frac{p_i - 1}{p_i} \ ag{Euler Function}
]
观察上式得出 (N) 会少一个因子 (p_i) ,同时多出 (p_i - 1) 的因子;
注意到对于质因子 (p (p > 2)),一定有(2 | p - 1),所以必然多出一个因子 (2),同时增加一些其他质因子;
故只需要计算整个过程中 (2) 的个数,线筛即可;
特判一开始是否有因子 (2),有的话答案要加 (1) (产生 (2) )。
(Source):
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
const int N = 1e5 + 5;
int n;
int pri[N], f[N], min_pri[N];
void prep() {
for (int i = 2; i < N; ++i) {
if (!min_pri[i]) {
min_pri[i] = i;
pri[++pri[0]] = i;
}
for (int j = 1, tmp; j <= pri[0] && i * pri[j] < N; ++j) {
tmp = i * pri[j];
min_pri[tmp] = pri[j];
if (!(i % pri[j]))
break;
}
}
f[2] = 1;
for (int i = 3; i < N; ++i)
if (min_pri[i] == i)
f[i] = f[i - 1];
else
f[i] = f[i / min_pri[i]] + f[min_pri[i]];
}
int main() {
//freopen("in", "r", stdin);
prep();
int T = in();
while (T--) {
unsigned long long res = 0;
n = in();
for (int i = 1, x; i <= n; ++i) {
x = in();
if (x == 2)
--res;
res += 1ull * f[x] * in();
}
printf("%llu
", res + 1);
}
return 0;
}