链接:拆拆
一开始想的是预处理出1e6内所有数的质因子,然后,对于y个空位就不会排列组合了。。准备用多重集容斥原理什么的乱搞,,但是还是很容易发现会TLE。
做法:
对于数X的多种质因子,先只放其中一种到y个盒子里去就好了,剩下的继续放,互相是不影响的,而同种质因子放进y个盒子很显然是多重集的组合数的结论。于是这题就结束了。
筛出1e6内所有数的质因子,快的做法就是线性筛出所有数的最小质因子,然后对于每个数,不断地除以最小质因子,就出结果了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5, mod = 1e9 + 7;
int v[N], p[N];
struct node{
int x, val;
};
vector<node> d[N];
int f[N], inv[N];
int qpow (int x, int n)
{
int ret = 1;
while (n) {
if (n & 1) ret = ret * x % mod;
x = x* x % mod;
n >>= 1;
}
return ret;
}
void init(int n)
{
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (v[i] == 0) {
v[i] = i;
p[++cnt] = i;
}
for (int j = 1; j <= cnt; j++) {
if (p[j] > v[i] || p[j] * i > n) break;
v[i * p[j]] = p[j];
}
}
for (int i = 2; i <= n; i++) {
unordered_map<int, int> f;
int num = i;
while(num != 1) {
f[v[num]]++;
num /= v[num];
}
for (auto j : f) d[i].push_back(node{j.first, j.second});
}
f[0] = inv[0] = 1;
for (int i = 1; i <= n; i++) f[i] = f[i - 1] * i % mod;
inv[n] = qpow(f[n], mod - 2);
for (int i = n - 1; i >= 1; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
}
int C(int n, int m)
{
return f[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main()
{
init(1000000);
int tt;
cin >> tt;
while(tt--)
{
int x, y;
scanf("%lld%lld", &x, &y);
int ans = 1;
for (auto i : d[x]) {
int n = y + i.val - 1, m = i.val;
ans = ans * C(n, m) % mod;
}
ans = ans * qpow(2, y - 1) % mod;
printf("%lld\n", ans);
}
return 0;
}