Codeforces 893E - Counting Arrays 【组合数】


E. Counting Arrays


time limit per test  3  seconds

memory limit per test      256 megabytes


You are given two positive integer numbers x and y. An array F is called an y-factorization of x iff the following conditions are met:

·   There are y elements in F, and all of them are integer numbers;

·   .

You have to count the number of pairwise distinct arrays thatare y-factorizations of x. Two arrays A and B are considered different iff there existsat least one index i (1 ≤ i ≤ y) such that Ai ≠ Bi. Since the answer can bevery large, print it modulo 109 + 7.

Input

The first line contains one integer q (1 ≤ q ≤ 105) — the number of testcasesto solve.

Then q lines follow, each containing two integers xi and yi (1 ≤ xi, yi ≤ 106). Each of these linesrepresents a testcase.

Output

Print q integers. i-th integer has to be equal to the number of yi-factorizations of xi modulo 109 + 7.

Example

Input

2
6 3
4 2

Output

36
6

Note

In the second testcase of the example there are six y-factorizations:

·   { - 4,  - 1};

·   { - 2,  - 2};

·   { - 1,  - 4};

·   {1, 4};

·   {2, 2};

·   {4, 1}.

 

【题意】


给出两个数x、y,问有多少种排列F1,F2,F3……Fn,使得它们的乘积为y,答案模1e9+7。


【思路】


我们首先对x分解质因数,分解成p1c1+ p2c2……的形式。


然后先不考虑符号,把排列中的数Fi都置为1,然后依次处理每个底数,假设它的指数为C,那么这里贡献的次数便是将C个底数分配到y个位置的情况数目。


转化一下,便是放球问题中的球相同,盒子不同,允许空盒的方案数,具体可以看这份博客:传送门


然后每个底数的贡献相乘即可。


最后再考虑符号,我们很容易发现,其实对于y个数的情况,前y-1个数的符号可以任意取定,只要利用最后一个数的符号使得乘积为正即可。



#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 2000005;
const ll mod = 1e9+7;
const ll INF = 1e15;
const double eps = 1e-9;

ll fac[maxn];
ll inv[maxn];

ll fast_mod(ll a,ll n,ll Mod)
{
    ll ans=1;
    a%=Mod;
    while(n)
    {
        if(n&1) ans=(ans*a)%Mod;
        a=(a*a)%Mod;
        n>>=1;
    }
    return ans;
}

void init()
{
    fac[0]=1;
    for(int i=1;i<maxn;i++)
    {
        fac[i]=(fac[i-1]*i)%mod;
    }
    inv[maxn-1]=fast_mod(fac[maxn-1],mod-2,mod);
    for(int i=maxn-2;i>=0;i--)
    {
        inv[i]=(inv[i+1]*(i+1))%mod;
    }
}

ll C(int n,int m)
{
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}

int main()
{
    init();
    rush()
    {
        int x,y;
        scanf("%d%d",&x,&y);
        vector<int>vec;
        for(int i=2;i*i<=x;i++)     //分解质因数
        {
            if(x%i==0)
            {
                int cnt=0;
                while(x%i==0)
                {
                    cnt++;
                    x/=i;
                }
                vec.push_back(cnt);
            }
        }
        if(x>1) vec.push_back(1);
        ll ans=1;
        y--;
        for(int i=0;i<vec.size();i++)
        {
            ans*=C(vec[i]+y,y);                 //模拟放球
            ans%=mod;
        }
        ans=(ans*fast_mod(2,y,mod))%mod;        //处理符号
        printf("%I64d\n",ans);
    }
}










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值