E. Bash Plays with Functions

题面

题解

首先考虑\(f_0(n)\)
不难发现\(f_0(n)=f_0(p_1^{\alpha 1}p_2^{\alpha 2}···p_k^{\alpha k})=2^k\)
对于互质的两个数p,q
不难发现\(f_0(pq)=f_0(p)f_0(q)=2^{p+q}\)
\(f_0(n)\)积性函数

既然知道了\(f_0(n)\)的性质,那么可以尝试判断一下\(f_r(n)\)的性质
因为\(f_{1}(n)=\sum_{u*v=n}\frac{f_0(u)+f_0(v)}{2}=\sum_{d|n}f_0(d)\)
\(n=p*q\)
\(f_1(n)=\sum_{d_1|q}\sum_{d_2|p}f_0(d_1d_2)=\sum_{d_1|q}f_0(d_1)\sum_{d_2|p}f_0(d_2)=f_1(q)f_1(p)\)
所以\(f_1(n)\)为积性函数,同理\(f_r(n)\)也为积性函数
\(f_r(n)=f_r(p_1^{\alpha 1}p_2^{\alpha 2}···p_k^{\alpha k})=f_r(p_1^{\alpha1})f_r(p_2^{\alpha2})···f_r(p_k^{\alpha k})\)
则只要求出每个\(f_r(p^i)\)即可
\(f_{r+1}(p^i)=\sum_{k=0}^{i}f_r(p^k)\),显然对每个p都一样
则设\(dp[r][i]=f_r(p^i)= \sum_{k=0}^{i} dp[r-1][k]\)
\(f_r(n)=f_r(p_1^{\alpha 1}p_2^{\alpha 2}···p_k^{\alpha k})=dp[r][\alpha1]\cdot dp[r][\alpha2]···\cdot dp[r][\alpha k]\)
因为\(a_i<=10^6,则p^i中i<20\)
则时间复杂度为\(O(10^7*20+qlogn)\)

点击查看代码
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<deque>
#define ll long long 
using namespace std;
const int maxn=1e6+101;
const int MOD=1e9+7;
const int inf=2147483647;
int read(){
    int x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x*f;
}
int q,r,n;
ll dp[maxn][21];
int tot,is[maxn],prime[maxn];
void getprime(){
    for(int i=2;i<=maxn;i++){
        if(!is[i])prime[++tot]=i;
        for(int j=1;j<=tot && i<=maxn/prime[j];j++){
            is[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
void init(){
    getprime();
    dp[0][0]=1;for(int i=1;i<=20;i++)dp[0][i]=2;
    for(int i=1;i<=1e6;i++){
        dp[i][0]=dp[i-1][0];
        for(int j=1;j<=20;j++)dp[i][j]=(dp[i][j-1]+dp[i-1][j])%MOD;
    }
}
int main(){
    q=read();init();
    while(q--){
        r=read();n=read();
        ll ans=1;
        for(int i=1;i<=tot && prime[i]<=sqrt(n);i++){
            if(n%prime[i])continue;int cnt=0;
            while(n%prime[i]==0){cnt++;n/=prime[i];}
            ans=ans*(ll)dp[r][cnt]%MOD;
        }
        if(n>1)ans=ans*(ll)dp[r][1]%MOD;
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2021-10-31 22:39  I_N_V  阅读(38)  评论(0编辑  收藏  举报