757E. Bash Plays with Functions 题解
757E. Bash Plays with Functions
题意:定义函数
给定 \(q\) 次询问,每次询问给出 \(r,n\),输出 \(f_r(n)\) 答案对 \(1e9 + 7\) 取模
解法:积性函数
首先把柿子化成容易计算的形式,从 \(f_0(n)\) 开始
将 \(n\) 分解成 \(n = p_1^{\alpha_1} * p_2^{\alpha_2} * ...*p_k^{\alpha_k}\)
那么根据定义,\(u = p_1^{\beta_1} * p_2^{\beta_2} * ... *p_k^{\beta_k}\),\(v = \frac{n}{u}\)
由于 \(gcd(u, v) = 1\),所以 \(\forall i \in [1, k],\beta_i = 0 \, or \,\alpha_i\)
故 \(f_0(n) = 2^k\),注意到其与具体的值无关,只与次数有关。
容易看出 \(f_0(n)\) 是一个积性函数
可以看出,\(\forall d | n\),\(f_r(d)\) 都枚举了两次,故可以进一步化简为
设 \(f_r(n)\) 为积性函数,接下来证明 \(f_{r + 1}(n)\) 也是积性函数
(抱歉不知道如何对齐)
根据数学归纳法,\(f_r(n)\) 是积性函数
那么对于任何一次询问,设 \(n = p_1^{\alpha_1} * p_2^{\alpha_2} * ...*p_k^{\alpha_k}\),我们只需要算出 \(f_r(p_i^{\alpha_i})\),然后根据积性函数的性质乘起来即可。
接下来的递推求解即可,注意到函数的值与质数大小无关,只与次数有关,故该函数可以在 \(n log^2 n\) 的时间内完成
接下来只要对每次询问,分解出 \(n\) 即可,注意到 \(n\) 只有 \(1e6\),可以预处理下每个数的最小质因子,然后递推回 \(1\) 即可,可以在 \(logn\) 的时间内完成,总复杂度为 \(O(nlog^2n + n + qlogn)\)
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e6 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
LL f[N][22];
bool st[N];
int last[N], pr[N], num;
void init() {
int n = 1000000;
for (int i = 0; i <= n; i ++ ) f[i][0] = 1;
for (int j = 1; j <= 20; j ++ ) {
for (int i = 0; i <= n; i ++ ) {
if (i == 0) f[i][j] = 2;
else if (i == 1) f[i][j] = 1 + 2 * j;
else for (int k = 0; k <= j; k ++ ) f[i][j] = (f[i][j] + f[i - 1][k]) % MOD;
}
}
for (int i = 2; i <= n; i ++ ) {
if (!st[i]) pr[++ num] = i, last[i] = i;
for (int j = 1; 1ll * pr[j] * i <= n; j ++ ) {
st[i * pr[j]] = true;
last[i * pr[j]] = pr[j];
if (i % pr[j] == 0) break;
}
}
}
inline void solve() {
int r, n; cin >> r >> n;
LL res = 1;
while (n != 1) {
int cnt = 0, p = last[n];
while (n % p == 0) n /= p, cnt ++;
res = res * f[r][cnt] % MOD;
}
cout << res << endl;
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
init();
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}

浙公网安备 33010602011771号