Codeforces893E

来源:互联网 发布:js post 跨域解决方案 编辑:程序博客网 时间:2024/06/14 18:30

题目链接:http://codeforces.com/problemset/problem/893/E

题意:给出Q次询问,每次询问给出X,Y, 求有多少种长度为Y的序列满足其相乘得到X。

如X=4,Y= 2可由以下6种得到:

  • { - 4,  - 1};
  • { - 2,  - 2};
  • { - 1,  - 4};
  • {1, 4};
  • {2, 2};
  • {4, 1}.



首先将X用唯一分解定理分解X = P1^a1 * P2^a2 * .....Pk^ak,记录下每个每个素数的指数,然后就转换成k个互相独立的事件,假设当前处理的为Pi^ai,就等价于现在有Y个盒子,有ai个不同的球往Y个盒子里面放,盒子允许为空的操作,经典的组合问题.C(ai, y+ai-1),预处理下阶乘,在每次求下逆元即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 2e6 + 7;const ll mod = 1e9 + 7;int q;ll a[30], x, y, fac[N], two[N];ll qmod(ll n, ll k){    ll ans = 1;    while(k) {        if(k&1) ans = ans * n % mod;        k>>=1;        n = n * n % mod;    }    return ans % mod;}ll inv(ll n){    return qmod(n, mod-2);}ll C(ll m, ll n){    ll M = fac[m];    ll NM = fac[n]*fac[m-n]%mod;    NM = M*inv(NM)%mod;    return NM;}void init(){    fac[0] = 1;    two[0] = 1;    for(int i = 1;i < N;i ++) {        two[i] = two[i - 1] * 2LL % mod;        fac[i] = fac[i - 1] * i % mod;    }}int main(){    init();    scanf("%d",&q);    while(q --) {        memset(a, 0, sizeof(a));        int tot = 0;        ll ans = 1;        scanf("%lld%lld",&x,&y);        for(int i = 2;i * i <= x;i ++) {            if(x % i == 0) {                tot ++;                while(x % i == 0) {                    a[tot] ++; x /= i;                }            }        }        if(x!=1) a[++tot] = 1;        for(int i = 1;i <= tot;i ++) ans = ans*C(y+a[i]-1,a[i]) % mod;        ans = ans * two[y-1] % mod;        printf("%lld\n",ans);    }    return 0;}