description
solution
The number of yyds that meet the conditions is actually the same as nnn (not the meaning of the title) is inextricably linked to the arithmetic sequence formula,
so the specific value can be divided into two
. The value range of the final answer must grow into[,) [,)[,) , the left is closed and the right is opened,
and the two boundaries must be the one with the smallest difference1 11 , then the binary aspect of the answer is also fixed and the
same is divided into1 1The specific position of 1 can be
linked here with the number of combinations, which can preprocess a small number of combinations to reduce query time complexity
Privately think that it is still difficult to think!
code
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define MAX 1e18
#define ll long long
#define mod 998244353
ll c[3005][3005];
ll qkpow1( ll x, ll y ) {
ll ans = 1;
while( y ) {
if( y & 1 ) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll qkpow2( ll x, ll y ) {
ll ans = 1;
while( y ) {
if( y & 1 ) ans *= x;
x *= x;
y >>= 1;
}
return ans;
}
ll calc( ll n ) {
return n * ( n + 1 ) >> 1;
}
ll C( ll n, ll m ) {
if( n <= 3000 && m <= 3000 ) return c[n][m];
if( m > n - m ) m = n - m;
if( n >= 1e7 && m >= 3 ) return MAX + 1;
__int128 d1 = 1, d2 = 1;
for( int i = 1;i <= m;i ++ ) d1 *= i;
for( int i = n - m + 1;i <= n;i ++ ) {
d2 *= i;
if( d2 > d1 * MAX ) return MAX + 1;
}
return d2 / d1;
}
void solve( ll n, ll k, ll ans ) {
ll t = 0, tmp;
while( k > ( tmp = C( n, t ) ) ) k -= tmp, t ++;
int last = n;
for( ll i = 1;i <= t;i ++ ) {
ll l = 1, r = last, pos;
while( l <= r ) {
ll mid = ( l + r ) >> 1;
if( C( mid - 1, t - i + 1 ) < k ) pos = mid, l = mid + 1;
else r = mid - 1;
}
last = pos - 1;
k -= C( pos - 1, t - i + 1 );
ans = ( ans + qkpow1( 2, pos - 1 ) ) % mod;
}
printf( "%lld\n", ans );
}
void init( int n = 3000 ) {
for( int i = 0;i <= n;i ++ )
for( int j = 1;j <= i;j ++ )
c[i][j] = MAX + 1;
for( int i = 0;i <= n;i ++ ) {
c[i][0] = 1;
for( int j = 1;j <= i;j ++ )
c[i][j] = min( c[i][j], c[i - 1][j] + c[i - 1][j - 1] );
}
}
int main() {
init();
int T; ll n, k;
scanf( "%d", &T );
while( T -- ) {
scanf( "%lld %lld", &n, &k );
ll t = sqrt( n << 1 );
while( calc( t ) > n ) t --;
ll t1 = n - calc( t ), t2 = t - t1;
if( ! t1 ) {
if( k == 1 ) printf( "%lld\n", ( qkpow1( 2, t ) - 1 + mod ) % mod );
else printf( "-1\n" );
}
else if( t2 < 60 && qkpow2( 2, t2 ) < k )
printf( "-1\n" );
else solve( t2, k, ( qkpow1( 2, t1 ) - 1 + mod ) % mod * qkpow1( 2, t2 + 1 ) % mod );
}
return 0;
}