题目描述
Sakiko有两个数字 x,yx,yx,y ,她想知道,有多少种方式可以将 xxx 拆成 yyy 个正整数的乘积。
例如 x=6,y=2x=6,y=2x=6,y=2 时,有 6×1=6,3×2=6,2×3=6,1×6=66 \times 1=6,3 \times 2=6,2 \times 3=6,1 \times 6=66×1=6,3×2=6,2×3=6,1×6=6 这 4 种方法。
由于这个答案可能很大,因此你需要输出答案对 109+710^9 + 7109+7 取模后的结果。
输入描述:
第一行输入一个正整数 T(1≤T≤103)T(1 \leq T \leq 10^3)T(1≤T≤103) ,表示询问次数。接下来 TTT 行,每行输入两个正整数 x,y(1≤x,y≤109)x,y(1 \leq x,y \leq 10^9)x,y(1≤x,y≤109) ,表示询问。
输出描述:
对于每个询问,在一行中输出一个整数表示答案。由于这个答案可能很大,因此你需要输出答案对 109+710^9 + 7109+7 取模后的结果。
示例1
输入
复制2 6 2 12 2
2 6 2 12 2
输出
复制4 6
4 6
说明
第 2 个询问: [12,1],[6,2],[4,3],[3,4],[2,6],[1,12] 答案为6
代码
#include<bits/stdc++.h>
using namespace std;
int t;
long long x,y;
const long long esp=1e9+7;
long long ksm(long long a,long long b){if(b==0) return 1;long long tmp=a%esp;long long res=1;while(b){if(b%2) res=res*tmp%esp;b/=2;tmp=tmp*tmp%esp;}return res%esp;
}
int main(){scanf("%d",&t);while(t--){scanf("%lld%lld",&x,&y);long long ans=1;for(int i=2;i<=sqrt(x);i++){if(x%i) continue;int d=0;while(x%i==0) x/=i,d++;//求C(y-1,y+d-1),即C(d,y+d-1) 隔板法(保证n>=m)long long res=1;for(int j=y;j<=y+d-1;j++){res=res*j%esp;res=res*ksm(y+d-j,esp-2)%esp;}ans=ans*res%esp;}if(x>1){int d=1;long long res=1;for(int j=y;j<=y+d-1;j++){res*=j%esp;res*=ksm(y+d-j,esp-2)%esp;}ans=ans*res%esp;}cout<<ans<<endl;}
}