「CF757E」 Bash Plays with Functions

题意

\(\omega(n)\) 表示 \(n\) 的质因子个数,定义

\[\begin{equation} f_r(n)=\left\{ \begin{aligned} &\sum\limits_{p\cdot q=n} [\gcd(p,q)=1] ,& r=0 \\ &\sum\limits_{u\cdot v=n} \frac{f_{r-1}(u)+f_{r-1}(v)}{2} ,& r\ge 1 \end{aligned} \right. \end{equation} \]

给出 \(q\)\(r,n\),求出 \(f_r(n)\) 的值。

分析

先考虑 \(r=0\) 的情况,因为 \(p,q\) 互质,所以两数没有共同质因子,答案即把 \(\omega(n)\) 个质因子分成两份的方案数,答案为 \(2^{\omega(n)}\)

考虑 \(r=1\) 的情况,由唯一分解定理,\(n=p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}(p_i\in\mathbb{P})\),则 \(f_1(n)=\sum\limits_{d|n}f_0(d)\),由 \(f_0(d)=2^{\omega(d)}\) 为积性函数,考虑把每个 \(d\) 分解成这些质因子,可得 \(f_1(n)=f_1(p_1^{a_1})f_1(p_2^{a_2})\cdots f_1(p_k^{a_k})\),所以 \(f_1(n)\) 也是积性函数。

\(r>1\) 时,因为不要求分出来的两个数互质,把式子展开得 \(f_r(n)=\sum f_{r-1}(p_1^{b_1}p_2^{b_2}\cdots p_k^{b_k})\),其中 \(b_i\in[0,a_i]\),且所有数互不相同,那这样就是一个多项式乘法的形式,由 \(f_r(p_i^{a_i})=\sum\limits_{j=0}^{a_i}f_{r-1}(p_i^{j})\),得到同上的式子,所以 \(f_r(n)\) 为积性函数。

可以发现 \(f_r(p_i^{a_i})\) 的值与 \(p_i\) 的大小没有关系,可以递推求 \(r,b_i\) 固定的函数值,因为 \(n\le 10^6\),所以 \(b_i<20\),可以递推预处理。

询问时用积性函数的性质把 \(n\) 分解,求质因子函数值的乘积即可。但是 \(\sqrt n\) 直接分解太慢了,可以先筛出 \([2,10^6]\) 的最大质因子,分解时除这个因子,统计次数,这样最多是 \(O(\log n)\) 的。

复杂度 \(O(20r+q\log n)\)

Code

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
// static char buf[100],*p1=buf,*p2=buf,obuf[100],*p3=obuf;
// #define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++
// #define putchar(x) (p3-obuf<100)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
mt19937_64 rnd(chrono::system_clock::now().time_since_epoch().count());
#define dbg(x) cout<<#x<<": "<<x<<"\n"
#define usetime() printf("time: %.3lfs\n",clock()*1.0/CLOCKS_PER_SEC)
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
inline void write(ll x){if(!x){putchar(48);putchar('\n');return;}short top=0,s[40];if(x<0)x=-x,putchar(45);while(x)s[top++]=x%10^48,x/=10;while(top--)putchar(s[top]);putchar('\n');}
namespace tobe{
    const ll maxn=1e6+5,mod=1e9+7;
    ll q,r,n,f[maxn][20],mx[maxn];
    bitset<maxn>vis;
    inline void mian(){
        f[0][0]=1;
        for(ll i=1;i<20;++i)f[0][i]=2;
        for(ll i=1;i<=1e6;++i){
            ll sum=0;
            for(ll j=0;j<20;++j){
                sum=(sum+f[i-1][j])%mod;
                f[i][j]=sum;
            }
        }
        for(ll i=2;i<=1e6;++i){
            if(vis[i])continue;
            for(ll j=i;j<=1e6;j+=i){
                mx[j]=i,vis.set(j);
            }
        }
        q=read();
        while(q--){
            r=read(),n=read();
            ll ans=1;
            while(n>1){
                ll now=mx[n],cnt=0;
                while(n%now==0)++cnt,n/=now;
                ans=ans*f[r][cnt]%mod;
            }
            write(ans);
        }
    }
}
signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ll t=1;
    while(t--)tobe::mian();
    // fwrite(obuf,p3-obuf,1,stdout);
    return 0;
}
posted @ 2025-02-09 17:18  run-away  阅读(14)  评论(0)    收藏  举报