757E. Bash Plays with Functions 题解

757E. Bash Plays with Functions

题意:定义函数

f0(n)=uv=n[gcd(u,v)=1]

fr+1(n)=uv=nfr(u)+fr(v)2

给定 q 次询问,每次询问给出 r,n,输出 fr(n) 答案对 1e9+7 取模

解法:积性函数

首先把柿子化成容易计算的形式,从 f0(n) 开始

n 分解成 n=p1α1p2α2...pkαk

那么根据定义,u=p1β1p2β2...pkβkv=nu

由于 gcd(u,v)=1,所以 i[1,k],βi=0orαi

f0(n)=2k,注意到其与具体的值无关,只与次数有关。

容易看出 f0(n) 是一个积性函数

fr+1(n)=uv=nfr(u)+fr(v)2=d|nfr(d)+fr(nd)2

可以看出,d|nfr(d) 都枚举了两次,故可以进一步化简为

fr+1(n)=d|n2fr(d)2=d|nfr(d)

fr(n) 为积性函数,接下来证明 fr+1(n) 也是积性函数

fr+1(pq)=d|pqfr(d)

=d1d2|pqfr(d1d2)

=d1d2|pqfr(d1)fr(d2)(fr(n))

=d1|pfr(d1)d2|qfr(d2)=fr+1(p)fr+1(q)

(抱歉不知道如何对齐)

根据数学归纳法,fr(n) 是积性函数

那么对于任何一次询问,设 n=p1α1p2α2...pkαk,我们只需要算出 fr(piαi),然后根据积性函数的性质乘起来即可。

f0(pα)=1

f1(pα)=1+2α

fr(pα)=i=0αfr1(pi)

接下来的递推求解即可,注意到函数的值与质数大小无关,只与次数有关,故该函数可以在 nlog2n 的时间内完成

接下来只要对每次询问,分解出 n 即可,注意到 n 只有 1e6,可以预处理下每个数的最小质因子,然后递推回 1 即可,可以在 logn 的时间内完成,总复杂度为 O(nlog2n+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;
}
posted @   Time_Limit_Exceeded  阅读(40)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示