Skip to content

Commit a4cb5be

Browse files
Add files via upload
1 parent 0ab67f7 commit a4cb5be

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#pragma GCC optimize("Ofast")
2+
#pragma GCC optimize("unroll-loops")
3+
#include <bits/stdc++.h>
4+
using namespace std;
5+
6+
typedef long long ll;
7+
typedef vector<int> vi;
8+
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
9+
10+
ll n, k;
11+
ll logk;
12+
constexpr ll MOD = 998244353;
13+
14+
int _sieve_size;
15+
constexpr ll inf = 1e18;
16+
vector<ll> lowestpf, primes;
17+
void smallestPF(ll upperbound = (ll) 1e5+2){
18+
_sieve_size = upperbound + 1;
19+
lowestpf.assign(_sieve_size, inf);
20+
21+
for(ll i = 2; i < _sieve_size; i++){
22+
if(lowestpf[i] == inf){
23+
lowestpf[i] = i;
24+
for(ll j = i * i; j < _sieve_size; j += i){
25+
lowestpf[j] = min(lowestpf[j], i);
26+
}
27+
primes.push_back(i);
28+
}
29+
}
30+
} // Time: O(n log log n)
31+
32+
constexpr ll mod(ll a, ll n) { return (a % n + n) % n; }
33+
constexpr ll extEuclid(ll a, ll b, ll &x, ll &y) { // pass x and y by ref
34+
ll xx = y = 0;
35+
ll yy = x = 1;
36+
while (b) { // repeats until b == 0
37+
ll q = a / b;
38+
tie(a, b) = tuple(b, a % b);
39+
tie(x, xx) = tuple(xx, x - q * xx);
40+
tie(y, yy) = tuple(yy, y - q * yy);
41+
}
42+
return a; // returns gcd(a, b)
43+
// ax + by = gcd(a, b)
44+
}
45+
constexpr ll modInverse(ll a, ll n = MOD) { // returns modular inverse of a mod n
46+
ll x, y;
47+
extEuclid(a, n, x, y);
48+
return mod(x, n);
49+
}
50+
51+
52+
ll memo_comb[50][50];
53+
ll comb(int nn, int r){
54+
assert(nn >= 0 && r >= 0);
55+
if (r == 0 || nn == r) return 1;
56+
if (nn < r) return 0;
57+
if (memo_comb[nn][r] != -1) return memo_comb[nn][r];
58+
return memo_comb[nn][r] = (comb(nn - 1, r - 1) + comb(nn - 1, r)) % MOD;
59+
}
60+
61+
ll stars(int stars, int bins){
62+
return comb(stars + bins - 1, bins - 1);
63+
}
64+
65+
vector<vector<ll>> f;
66+
67+
int main(){
68+
smallestPF();
69+
memset(memo_comb, -1, sizeof memo_comb);
70+
int tc;
71+
cin >> tc;
72+
while(tc--){
73+
cin >> k >> n;
74+
logk = 1;
75+
while ((1LL << logk) <= k) logk++;
76+
77+
f.assign(k+2, vector<ll>(logk+2, 0));
78+
for (int x=2; x<=k; x++){
79+
int p = lowestpf[x];
80+
int y = x;
81+
int q = 0;
82+
while (y % p == 0){
83+
y /= p;
84+
q++;
85+
}
86+
87+
if (y == 1){
88+
for (int a=1; a<=logk; a++){
89+
f[x][a] = stars(q-a, a);
90+
}
91+
}
92+
else{
93+
for (int a=1; a<=logk; a++){
94+
for (int fresh=0; fresh<a; fresh++){
95+
f[x][a] += ((comb(a, fresh) * f[y][a-fresh]) % MOD) * stars(q-fresh, a) % MOD;
96+
f[x][a] %= MOD;
97+
}
98+
}
99+
}
100+
}
101+
102+
vector<ll> np1choose(logk+5, 0);
103+
for (ll a=1; a<np1choose.size(); a++){
104+
ll num = 1;
105+
for (int i=0; i<a; i++){
106+
num = (num * (n+1-i)) % MOD;
107+
}
108+
109+
ll den = 1;
110+
for (int i=1; i<=a; i++){
111+
den = (den * i) % MOD;
112+
}
113+
114+
ll deninv = modInverse(den);
115+
np1choose[a] = (num * deninv) % MOD;
116+
}
117+
118+
cout << n << " "; // 1 is handled separately
119+
120+
for (int x =2; x<=k; x++){
121+
ll ans = 0;
122+
for (int i=1; i<=min(n, logk); i++){
123+
ans += (f[x][i] * np1choose[i+1]) % MOD;
124+
ans %= MOD;
125+
}
126+
cout << ans << " ";
127+
}
128+
cout << endl;
129+
}
130+
131+
132+
return 0;
133+
}

0 commit comments

Comments
 (0)