cf 893 E

有 q 次询问,第 i 次询问包含两个数 x, y 。 
求满足下面两个要求的 F 数组的方案数。 
1.  F 数组由 y 个整数构成 
2. x=\prod_{i=1}^{y}F_i  
A与B不同当且仅当至少存在一个数 i(1\le i\le y) 满足 A_i ≠B_i 。答案对 10^9+7 取模 
数据范围: 1 ≤ q ≤ 10^5,1 ≤ x_i, y_i ≤ 10^6

显然对x分解质因数,如果某个质因子幂次为t,根据挡板法对答案的贡献就是 \binom{y+t-1}{t}

又因为可是是负的,每次挑选偶数个让它变成负的,那么答案就是 \binom{y}{0}+\binom{y}{2}+\binom y4 + \cdots=2^{y-1}

代码这里可以预处理一下2的次幂会更快一点,

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
ll qpow(ll a,ll x){
    ll res=1;
    while (x){
        if(x&1)
            res=res*a%mod;
        a=a*a%mod;
        x/=2;
    }
    return res;
}
int prime[1005],cnt=0,vis[1005];
ll up[2000005],inv[2000005],down[2000005];
void init(){
    for(int i=2;i<=1001;i++){
        if(vis[i])continue;
        prime[cnt++]=i;
        for(int j=2*i;j<=1001;j+=i){
            vis[j]=1;
        }
    }
    down[0]=up[0]=inv[1]=1;
    for(int i=2;i<=2e6;i++){
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
    for(int i=1;i<=2e6;i++){
        up[i]=up[i-1]*i%mod;
        down[i]=down[i-1]*inv[i]%mod;
    }
}
ll C(ll x,ll y){
    return up[x]*down[y]%mod*down[x-y]%mod;
}
int q,x,y;
int main(){
    //ios::sync_with_stdio(false);
    init();
    scanf("%d",&q);
    while (q--){
        scanf("%d%d",&x,&y);
        ll ans = 1;
        for(int i=0;prime[i]*prime[i]<=x&&i<cnt;i++){
            int cnt=0;
            while (x%prime[i]==0){
                x/=prime[i];
                cnt++;
            }
            if(cnt)ans=ans*C(y+cnt-1,cnt)%mod;
        }
        if(x!=1)ans=ans*y%mod;
        ans=ans*qpow(2,y-1)%mod;
        printf("%lld\n",ans);
    }
}
View Code

 

posted @ 2019-02-02 09:04  MXang  阅读(795)  评论(0编辑  收藏  举报