Each operation removes exactly one prime factor from some a_i.
Ifthen applying operations corresponds to removing prime factors.
Thus, we distribute removals among exponents:
The number of resulting values depends only on how many times each prime is removed.
Let pre[x][c] be the number of distinct values obtainable from using exactly operations.
Compute the smallest prime factor for all numbers up to 10^6 using a sieve.
Letwhere is the smallest prime factor and is not divisible by .
We remove copies of , where 0 \le k \le \min(c, e), and apply the remaining c-k operations to .
Base case:
Since 2^{20} > 10^6, any number has at most prime factors. Hence we cap c \le 20.
Let dp[i][j] be the number of distinct arrays formed from the first elements using exactly operations.
Base case:
Transition:
Final answer:
Precomputation: O(M \log \log M) for sieve and O(M \cdot 20) for DP.
Per test case: O(n \cdot k \cdot 20).
Space: O(M \cdot 20) for precomputation and for DP.</spoiler>
#include<bits/stdc++.h>
using namespace std;
const int MAX_VAL = 1000000;
const int MAX_OP = 20;
const int MOD = 998244353;
int spf[MAX_VAL + 1];
int pre[MAX_VAL + 1][MAX_OP + 1];
void globalPrecomputation() {
for (int i = 2; i <= MAX_VAL; i++) spf[i] = i;
for (int i = 2; i * i <= MAX_VAL; i++) {
if (spf[i] == i) {
for (int j = i * i; j <= MAX_VAL; j += i) {
if (spf[j] == j) spf[j] = i;
}
}
}
pre[1][0] = 1;
for (int op = 1; op <= MAX_OP; op++) pre[1][op] = 0;
for (int i = 2; i <= MAX_VAL; i++) {
int p = spf[i];
int temp = i;
int e = 0;
while (temp % p == 0) {
e++;
temp /= p;
}
// Note: Avg. value of e for all the values (1...MX) is around ~4, So the loop 2 doesn't really add much of complexity.
int y = temp;
for (int op = 0; op <= MAX_OP; op++) { // 1
pre[i][op] = 0;
for (int k = 0; k <= e; k++) { // 2
if (op - k >= 0) {
pre[i][op] += pre[y][op - k];
if(pre[i][op] >= MOD) pre[i][op] >= MOD;
}
}
}
}
}
void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<long long> dp(k + 1, 0);
dp[0] = 1;
for (int i = 0; i < n; i++) {
vector<long long> next_dp(k + 1, 0);
for (int j = 0; j <= k; j++) {
for (int c = 0; c <= MAX_OP; c++) {
if (j + c > k) break;
if (pre[a[i]][c] == 0) break;
next_dp[j + c] = (next_dp[j + c] + dp[j] * pre[a[i]][c]) % MOD;
}
}
dp.swap(next_dp);
}
long long ans = 0;
for (int j = 0; j <= k; j++) {
ans = (ans + dp[j]) % MOD;
}
cout << ans << endl;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
globalPrecomputation();
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}