Educational Codeforces Round 33 (Rated for Div. 2) E. Counting Arrays

题目链接
题意:给你两个数x,yx,y,让你构造一些长为yy的数列,让这个数列的累乘为xx,输出方案数。
思路:考虑对xx进行质因数分解,设某个质因子PiP_i的的幂为kk,则这个质因子的贡献就相当于把kkPiP_i放到yy个盒子中,且盒子可能为空,方案为C(k+y1,y)C(k+y-1,y),然后每个质因子的方案乘在一起即可。最后,因为负号也会出现,但xx为正,所以就是在yy个位置上选偶数个位置放负号,方案为2y12^{y-1}再乘起来即可。

#include<bits/stdc++.h>

#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back

using namespace std;

LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 2e6 +11;
const LL mod=1e9+7;
LL Fac[N+33],Inv[N+33];
int p[N+33],a[N+33],cnt;
void init(){
    Fac[0]=1;
    for(int i=1;i<=N;i++)Fac[i]=(Fac[i-1]*i)%mod;
    Inv[N]=powmod(Fac[N],mod-2,mod);
    for(int i=N-1;i>=1;i--)Inv[i]=(Inv[i+1]*(i+1))%mod;
    Inv[0]=1;
}
void P(){
    for(int i=2;i<N;i++){
        if(!p[i])a[++cnt]=i;
        for(int j=1;j<=cnt&&1ll*a[j]*i<N;j++){
            p[a[j]*i]=1;
            if(i%a[j]==0)break;
        }
    }
}
LL C(int x,int y){
    return 1ll*Fac[x]*Inv[y]%mod*Inv[x-y]%mod;
}
int main(){
    ios::sync_with_stdio(false);
    init();
    int t;
    P();
    for(cin>>t;t;t--){
        int x,y;
        cin>>x>>y;
        LL ans=1;
        for(int i=1;i<=cnt&&1ll*a[i]*a[i]<=x;i++){
            if(x%a[i]==0){
                int res=0;
                while(x%a[i]==0)res++,x/=a[i];
                ans=ans*C(res+y-1,y-1);
                ans%=mod;
            }
        }
        if(x>1)ans=ans*C(y,y-1)%mod;
        cout<<ans*powmod(2,y-1,mod)%mod<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/pubgoso/p/10759709.html