题目链接:https://codeforc.es/problemset/problem/893/E
题目大意:有次询问,每次给定,问满足序列长度为,且的序列数目,序列可为负。
思路:要计算满足条件的序列数目,首先想到的是将素因数分解,然后对于每次素因子,统计其出现的次数,要怎么把这个数分成份呢,我们就想到了隔板法,类似于将个小球放进个盒子中,可以放空。
那么对于来说,组合的种类数就是。
然后题目要求可以为负数,但是,所以负数只能出现偶数次,即对于个数来说,负数的种类数就是。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+10;
const int mod=1e9+7;
typedef long long ll;
ll qpow(ll x,ll y){
ll ans=1;
while(y>0){
if(y&1){
ans=ans*x%mod;
}
y>>=1;
x=x*x%mod;
}
return ans;
}
ll f[maxn];
ll inv[maxn];
void calf()
{
f[0]=1;
for(int i=1;i<maxn;i++){
f[i]=(f[i-1]*i)%mod;
}
inv[maxn-1]=qpow(f[maxn-1],mod-2);
for(int i=maxn-2;~i;i--){
inv[i]=inv[i+1]*(i+1)%mod;
}
}
ll C(int n,int m){
if(n<m||m<0){
return 0;
}
return f[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
int q;
int x,y;
int cnt;
calf();
scanf("%d",&q);
while(q--){
scanf("%d%d",&x,&y);
ll ans=1;
for(int i=2;i*i<=x;i++){
cnt=0;
if(x%i==0){
while(x%i==0){
x/=i;
cnt++;
}
ans=ans*C(cnt+y-1,y-1)%mod;
}
}
if(x>1){
ans=ans*y%mod;
}
ans=ans*qpow(2,y-1)%mod;
printf("%lld\n",ans);
}
return 0;
}
隔板法参考:https://blog.csdn.net/qq_39942341/article/details/80246780