結果

問題 No.2303 Frog on Grid
ユーザー Jeroen Op de BeekJeroen Op de Beek
提出日時 2023-05-12 23:00:06
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 176 ms / 2,000 ms
コード長 3,923 bytes
コンパイル時間 3,831 ms
コンパイル使用メモリ 220,368 KB
実行使用メモリ 27,228 KB
最終ジャッジ日時 2023-08-19 05:52:31
合計ジャッジ時間 7,396 ms
ジャッジサーバーID
(参考情報)
judge12 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 38 ms
21,060 KB
testcase_01 AC 38 ms
21,100 KB
testcase_02 AC 172 ms
26,928 KB
testcase_03 AC 103 ms
23,240 KB
testcase_04 AC 173 ms
26,488 KB
testcase_05 AC 172 ms
26,700 KB
testcase_06 AC 103 ms
23,416 KB
testcase_07 AC 173 ms
26,140 KB
testcase_08 AC 171 ms
26,320 KB
testcase_09 AC 70 ms
22,096 KB
testcase_10 AC 102 ms
23,324 KB
testcase_11 AC 70 ms
21,896 KB
testcase_12 AC 102 ms
23,536 KB
testcase_13 AC 38 ms
21,300 KB
testcase_14 AC 38 ms
21,060 KB
testcase_15 AC 38 ms
21,024 KB
testcase_16 AC 38 ms
21,148 KB
testcase_17 AC 38 ms
21,040 KB
testcase_18 AC 176 ms
27,012 KB
testcase_19 AC 174 ms
27,028 KB
testcase_20 AC 175 ms
27,056 KB
testcase_21 AC 176 ms
27,064 KB
testcase_22 AC 175 ms
27,228 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma") 
#include "bits/stdc++.h"
using namespace std;
#define all(x) begin(x),end(x)
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type> ostream& operator<<(ostream &os, const T_container &v) { string sep; for (const T &x : v) os << sep << x, sep = " "; return os; }
#define debug(a) cerr << "(" << #a << ": " << a << ")\n";
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> pi;

const int mxN = 1<<19, oo = 1e9;
const long long MOD =  998244353;
class mint {
public:
    int d;
    mint () {d=0;}
    mint (long long _d) : d(_d%MOD){};
    mint operator*(const mint& o) const {
        return ((ll)d*o.d)%MOD;
    }
    mint operator+(const mint& o) const {
        long long tmp = d+o.d;
        if(tmp>=MOD) tmp-=MOD;
        return tmp;
    }
    mint operator-(const mint& o) const {
        long long tmp = d-o.d;
        if(tmp<0) tmp+=MOD;
        return tmp;
    }
    mint operator^(long long b) const {
        mint tmp = 1;
        mint power = *this;
        while(b) {
            if(b&1) {
                tmp = tmp*power;
            }
            power = power*power;
            b/=2;
        }
        return tmp;
    }
    mint operator/(const mint& o) {
        return *this * (o^(MOD-2));
    }
    bool operator==(const mint& o) {
        return d==o.d;
    }
    friend mint& operator+=(mint& a, const mint& o) {
        a.d+=o.d;
        if(a.d>=MOD) a.d-=MOD;
        return a;
    }
};
typedef mint cd;
void revperm(cd* in, int n) {
    for(int i=0,j=0;i<n;++i) {
        if(i<j) swap(in[i],in[j]);
		for(int k = n >> 1; (j ^= k) < k; k >>= 1);
    }
}
cd w[mxN+1]; // stores w^j for each j in [0,n-1]
void precomp() {
    w[0] = 1;
    int pw = (MOD-1)/mxN;
    w[1] = mint(3)^pw;
    for(int i= 2;i<=mxN;++i) {
        w[i] = w[i-1]*w[1];
    }
}
void fft(cd* in, int n, bool reverse=false) {
    int lg = __lg(n);
    assert(1<<lg == n);
    int stride = mxN/n;
    revperm(in,n);
    for(int s=1;s<=lg;++s) {
        int pw = 1<<s;
        int mstride = stride*(n>>s);
        for(int j=0;j<n;j+=pw) {
            // do FFT merging on out array
            cd* even = in+j, *odd = in+j+pw/2;
            for(int i=0;i<pw/2;++i) {
                cd& power = w[reverse?mxN-mstride*i:mstride*i];
                auto tmp = power*odd[i];
                odd[i] = even[i] - tmp;
                even[i] = even[i] + tmp;
            }
        }
    }
    if(reverse) {
        mint fac = mint(1)/n;
        for(int i=0;i<n;++i) in[i]=in[i]*fac;
    }
}
int total;

vector<cd> polymul(vector<cd> a, vector<cd> b) {
    int n = a.size(), m = b.size(), ptwo = 1;
    while(ptwo<(n+m)) ptwo*=2;
    a.resize(ptwo), b.resize(ptwo);
    fft(a.data(),ptwo); 
    fft(b.data(),ptwo);
    for(int i=0;i<ptwo;++i) 
        a[i] = a[i]*b[i];
    fft(a.data(),ptwo,true);
    a.resize(n+m-1);
    return a;
}
const int mxF = 2e6+2;
mint fact[mxF], ifact[mxF];
mint ncr(int a, int b) {
    if(b>a or a<0 or b<0) return 0;
    return fact[a]*ifact[b]*ifact[a-b];
}
void precomp2() {
    fact[0]=1;
    for(int i=1;i<mxF;++i) {
        fact[i]=fact[i-1]*i;
    }
    ifact[mxF-1] = mint(1)/fact[mxF-1];
    for(int i=mxF-2;i>=0;--i) {
        ifact[i]=ifact[i+1]*(i+1);
    }
}
int main() {
    precomp();
    precomp2();
    int n,m; cin >> n >> m;
    vector<mint> a(n+1),b(m+1);
    for(int i=0;i<=n/2;++i) {
        a[n-i]=ncr(n-i,i)*ifact[n-i];
    }
    for(int i=0;i<=m/2;++i) {
        b[m-i] = ncr(m-i,i)*ifact[m-i];
    }
    auto c = polymul(a,b);
    mint ans=0;
    for(int i=0;i<c.size();++i) {
        ans+=c[i]*fact[i];
    }
    cout << ans.d << '\n';
    
}
0