AtCoder Beginner Contest 110 D - Factorization

D - Factorization


Time limit : 2sec / Memory limit : 1024MB

Score : 400 points

Problem Statement

You are given positive integers N and M.

How many sequences a of length N consisting of positive integers satisfy aa2×…×aN=M? Find the count modulo 109+7.

Here, two sequences a' and a'' are considered different when there exists some i such that ai'ai''.

Constraints

  • All values in input are integers.
  • 1≤N≤105
  • 1≤M≤109

Input

Input is given from Standard Input in the following format:

N M

Output

Print the number of the sequences consisting of positive integers that satisfy the condition, modulo 109+7.


Sample Input 1

Copy

2 6

Sample Output 1

Copy

4

Four sequences satisfy the condition: {a1,a2}={1,6},{2,3},{3,2} and {6,1}.


Sample Input 2

Copy

3 12

Sample Output 2

Copy

18

Sample Input 3

Copy

100000 1000000000

Sample Output 3

Copy

957870001

这题当时没做出来,当时不会用隔板法,后来去查了隔板数学方法,也就把这道题写出来了。

所以做这个题前,要掌握两个知识点——隔板法和逆元

因为逆元简单多见,隔板法少见,所以这里我就来说说隔板法,先来看一个问题

将20个大小形状完全相同的小球放入3个不同的盒子,允许有盒子为空,但球必须放完,有多少种不同的方法?

 

 

给个图引导一下就明白了

 

那么,这题中盒子可以为空,也就是说可以产生||和|||等的现象,这显然不太好计算

那我们补3个球,这样我们只要考虑3+20个球之间三块板的位置在哪里就好了,也就是两个球之间的板有或没有

间距有3+20-1=22个,插入两块板,也就是C(22,2)

然后每一种情况都可以获得3堆球x,y,z

那么球的真实数量是x-1,y-1,z-1

 

明白了隔板法我们来看这题

(1)首先任何一个大于1的整数都可以分解为p1^a1*p2^a2*……pn^an(p为素数序列,n>=1)

  (2)  我们知道一个素数p的个数为a,我们要把这a个p分成n份,我们就要用到上面说的隔板法,所以的到的结果是C(n+a-1,n-1)

(3)把这些组合数乘起来就是我们要的结果,因为有除法在其中,所以要用到逆元

 

#include<cstdio>
const int mod=1000000007;
long long power(long long a,int k){
    long long ans=1,y=a;
    while(k){
        if(k%2)
            ans=ans*y%mod;
        y=y*y%mod;
        k=k/2;
    }
    return ans;
}
long long fun[1<<17],ans=1;
int main(){
    long long n,m;
    scanf("%lld%lld",&n,&m);
    fun[0]=1;
    for(int i=1;i<1<<17;i++){
        fun[i]=fun[i-1]*i%mod;
    }
    for(int i=2;i*i<=m;i++){
        if(m%i==0){
            long long s=0;
            while (m%i==0) {
                m=m/i;
                s++;
            }
            ans=ans*fun[n+s-1]%mod*power(fun[n-1], mod-2)%mod*power(fun[s], mod-2)%mod;
        }
    }
    if(m>1)
        ans=ans*n%mod;
    printf("%lld\n",ans);
    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值