Codeforces893E

题目链接: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;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值