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