BZOJ 2749 - [HAOI2012]外星人
Published on 2017-01-20描述
设 为最少经过几次 的变换使得 。给定 的标准分解形式:
其中 。请你求 。
分析
拿到这题我们可以发现,暴力算是不行的, 会极大,而且 显然不具有积性之类的性质,我们要寻找一些性质来帮助解题。
我们考虑 的性质,首先是展开形式:
以及 时,满足 为偶数,这是因为 ,所以互质的数必然是成对出现。
当 时,由于只有 ,所以 必然要先变换到 ,然后才能变换到 。假设 是偶数,那么经过一次变换,所有质因子的指数会减少 ,取而代之的是 (这些都是偶数)。也就是说,这一次变换会去掉质因子 的一个指数,同时生成至少一个质因子 (只要 不是 的形式),那就是说,每次变换至少有一个 可以去掉,所以经过若干次变换,一定会变换到 的形式,此时还需要 步才能变到 。也就是说,我们在变换能生成多少个 ,我们就需要多少步来达到 。
对于奇数,假设能生成 个 ,需要 步才能变换到 ,原因是需要一步来生成一个 。
设 为 经过若干次 的变换中,会生成多少个 ,不难发现, 满足:
这样就可以使用线性筛法筛出 ,回答询问的时候,需要用到 ,同时需要有判断有无 这个质因子来确定奇偶性。
代码
// Created by Sengxian on 2017/01/20. // Copyright (c) 2017年 Sengxian. All rights reserved. // BZOJ 2749 数论 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int readInt() { static int n, ch; n = 0, ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) n = n * 10 + ch - '0', ch = getchar(); return n; } const int MAX_N = 100000 + 3; int primes[MAX_N], f[MAX_N], cnt = 0; bool isPrime[MAX_N]; void prepare() { fill(isPrime + 2, isPrime + MAX_N, true); f[2] = 1; for (int i = 2; i < MAX_N; ++i) { if (isPrime[i]) primes[cnt++] = i, f[i] = i == 2 ? 1 : f[i - 1]; for (int j = 0; j < cnt && i * primes[j] < MAX_N; ++j) { int t = i * primes[j]; isPrime[t] = false; f[t] = f[i] + f[primes[j]]; if (i % primes[j] == 0) break; } } } int main() { prepare(); int caseNum = readInt(); while (caseNum--) { int n = readInt(); ll ans = 0; bool flag = false; while (n--) { int p = readInt(), k = readInt(); flag |= p == 2; ans += (ll)f[p] * k; } printf("%lld\n", ans + (!flag)); } return 0; }