1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "cmath" #include "vector" #include "map" #include "set" #include "queue" using namespace std; #define MAXN 1000006
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i) #define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i) #define pii pair<int,int> #define fi first #define se second #define mp make_pair #define pb push_back #define eb emplace_back #define vi vector<int> #define all(x) (x).begin() , (x).end() #define mem( a ) memset( a , 0 , sizeof a ) typedef long long ll; #define P 998244353 #define lg2( x ) ( 31 - __builtin_clz( x ) ) int n , m; ll q;
int Pow( int x , int a ) { int ans = 1 , cur = x % P; while( a ) { if( a & 1 ) ans = 1ll * ans * cur % P; cur = 1ll * cur * cur % P , a >>= 1; } return ans; }
int Wn[2][MAXN] , rev[MAXN]; void getwn( int len ) { for( int mid = 1 ; mid < len ; mid <<= 1 ) { int w0 = Pow( 3 , ( P - 1 ) / ( mid << 1 ) ) , w1 = Pow( 3 , P - 1 - ( P - 1 ) / ( mid << 1 ) ); Wn[0][mid] = Wn[1][mid] = 1; for( int i = 1 ; i < mid ; ++ i ) Wn[0][mid + i] = 1ll * Wn[0][mid + i - 1] * w0 % P, Wn[1][mid + i] = 1ll * Wn[1][mid + i - 1] * w1 % P; } } void getr( int len ) { int t = __builtin_ctz( len ) - 1; for( int i = 1 ; i < len ; ++ i ) rev[i] = ( rev[i >> 1] >> 1 ) | ( ( i & 1 ) << t ); } void NTT( int* A , int len , int typ ) { rep( i , 0 , len - 1 ) if( i < rev[i] ) swap( A[i] , A[rev[i]] ); for( int mid = 1 ; mid < len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += ( mid << 1 ) ) for( int k = 0 ; k < mid ; ++ k ) { int t1 = A[i + k] , t2 = 1ll * A[i + k + mid] * Wn[typ][mid + k] % P; A[i + k] = (t1 + t2) % P , A[i + k + mid] = (t1 + P - t2) % P; } if( typ == 1 ) for( int inv = Pow( len , P - 2 ) , i = 0 ; i < len ; ++ i ) A[i] = 1ll * A[i] * inv % P; }
int J[MAXN] , iJ[MAXN]; int g[MAXN]; int a[MAXN] , b[MAXN] , iv2; inline int pp( const int& x ) { return ( x & 1 ) ? P - 1 : 1; } inline void mul( int *A , int *B , int n , int m , int bc = 0 ) { int len = 1; while( len <= n + m ) len <<= 1; rep( i , n + 1 , len ) A[i] = 0; rep( j , m + 1 , len ) B[j] = 0; getr( len ) , getwn( len ); NTT( A , len , 0 ) , NTT( B , len , 0 ); rep( i , 0 , len - 1 ) A[i] = A[i] * 1ll * B[i] % P; NTT( A , len , 1 ); if( !bc ) return; NTT( B , len , 1 ); } int C( int a , int b ) { return J[a] * 1ll * iJ[b] % P * iJ[a - b] % P; } void getg( int n ) { rep( i , 0 , n ) a[i] = pp( i ) * 1ll * iJ[i] % P * ( Pow( n - 2 * i , q ) % P + P ) % P , b[i] = iJ[i]; mul( a , b , n , n ); rep( i , 0 , n ) g[i] = a[i] * 1ll * J[i] % P * Pow( iv2 , i ) % P * C( n , i ) % P; }
int f1[MAXN] , f2[MAXN] , s1[MAXN] , s2[MAXN];
void solve() { cin >> n >> q >> m; if( 2 * m <= q - n ) return printf("%d\n",Pow( n , q ) ) , void(); if( 2 * m > q ) return puts("0") , void(); int t = q - 2 * m; q %= ( P - 1 ); iv2 = ( P + 1 ) / 2; J[0] = 1; int mx = n; rep( i , 1 , mx ) J[i] = J[i - 1] * 1ll * i % P; iJ[mx] = Pow( J[mx] , P - 2 ); per( i , mx - 1 , 0 ) iJ[i] = iJ[i + 1] * 1ll * ( i + 1 ) % P; getg( n ); rep( i , 0 , n ) a[i] = pp( n - i ) * 1ll * iJ[n - i] % P , b[i] = J[i] * 1ll * g[i] % P; int len = 1; mul( a , b , n , n ); int res = 0; rep( i , 0 , n ) if( i <= t ) f1[i] = a[i + n] * 1ll * iJ[i] % P , res = ( res + f1[i] ) % P; cout << res << endl; }
signed main() {
solve(); }
|