思路:质因子分解。
对于每个质因子,假设它有k个,那么求把它分配到y个数上的方案数。
相当于把k个小球分配到y个盒子里的方案数。
这个问题可以用隔板法(插空法)解决,要把一段分成y段,需要y-1个隔板,那么有y-1+k个位置,选y-1个位置为隔板,剩下的都是小球,那么方案数为C(y-1+k,y-1)。
如果全为正数,答案就是所有质因子方案数的积。
但是这道题目可以为负数,那么在这y个数里选偶数个变成负数
答案还要乘以C(y,0)+C(y,2)+C(y,4)+C(y,6)+... ③
这个问题是高中排列组合的一个经典问题,
设(1+x)^y=C(y,0)*x^0+C(y,1)*x^1+...+C(y,y-1)*x^(y-1)+C(y,y)*x^y
当x=1时,C(y,0)+C(y,1)+...+C(y,y-1)+C(y,y)=2^y ①
当x=-1时,C(y,0)-C(y,1)+C(y,2)-C(y-3)+...=0 ②
①+②=2*③
③式为2^(y-1)
代码:
By ZhihuiLiu, contest: Educational Codeforces Round 33 (Rated for Div. 2), problem: (E) Counting Arrays, Accepted, #, hack it! #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int MOD=1e9+7; const int N=1e6+5; ll fac[2*N]; ll q_pow(ll n,ll k) { ll ans=1; while(k) { if(k&1)ans=(ans*n)%MOD; n=(n*n)%MOD; k>>=1; } return ans; } void init() { fac[0]=1; for(int i=1;i<2*N;i++)fac[i]=(fac[i-1]*i)%MOD; } ll C(ll n,ll m) { return (fac[n]*q_pow(fac[m],MOD-2))%MOD*q_pow(fac[n-m],MOD-2)%MOD; } int main() { ios::sync_with_stdio(false); cin.tie(0); int q,x,y; init(); cin>>q; while(q--) { cin>>x>>y; int c=0; ll ans=q_pow(2,y-1); for(int i=2;i*i<=x;i++) { if(x%i==0) { int t=0; while(x%i==0) { t++; x/=i; } ans=(ans*C(t+y-1,t))%MOD; } } if(x>1)ans=(ans*y)%MOD; cout<<ans<<endl; } return 0; }
时间: 2024-10-08 05:37:30