版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011528035/article/details/54952669
题意:
给你两个数 n和r
可以做r次分解
当r大于0 n可以分解成两个因子u和v u*v=n
当r 等于0 n分解出的两个因子的gcd要为1
如题意所给的公式来计算最终结果
思路:
仔细观察 在 r相同的情况下 25 和 4 30和42 的答案是相同
是由于 他们的构成结构相同
即n=(a^x)*(b^y)*(c^z) ... a b c....为他们的素因数
而其实也可以得知 f(n,r)=f(a^x,r)*f(b^y,r)*f(c^z,r) .....
比如 36 (2^2)*(3^2) 2和3的方案分开独立计算 如果最后2和3都是合理的 那么他们合起来的也是合理的
所以只需考虑只有单因子即可
根据公式其实是 由于u和v是除于2的 且若u v不同 交换位置算不同次数
于是可以列出dp方程式
i 代表系数 r代表层数
dp[i][r]=dp[1][r-1]+dp[2][r-2]+dp[3][r-3]....
即可以算出答案
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
#define LL long long
#define MAX 1001000
#define MOD 1000000007
#define LIM 21
LL dp[LIM][MAX];
int p[MAX];
int v[MAX];
int cnt;
void init()
{
for(int i=2;i<MAX;i++)
{
if(!v[i])
{
v[i]++;
p[cnt++]=i;
}
for(int j=0;p[j]*i<MAX&&j<cnt;j++)
{
v[p[j]*i]=1;
if(i%p[j]==0)break;
}
}
dp[1][0]=1;
for(int i=2;i<LIM;i++)
{
dp[i][0]=2;
}
for(int i=1;i<MAX;i++)
for(int j=1;j<LIM;j++)
dp[j][i]=(dp[j-1][i]+dp[j][i-1])%MOD;
}
int main()
{
init();
int t,n,r;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&r,&n);
LL ans=1;
int tmp=sqrt(n);
for(int i=0;i<cnt&&tmp>=p[i];i++)
{
if(n%p[i]==0)
{
int x=1;
while(n%p[i]==0)
{
x++;
n/=p[i];
}
ans=(ans*dp[x][r])%MOD;
}
}
if(n!=1)
ans=(ans*dp[2][r])%MOD;
printf("%lld\n",ans);
}
return 0;
}