結果
問題 | No.2503 Typical Path Counting Problem on a Grid |
ユーザー | pockyny |
提出日時 | 2024-10-18 03:08:27 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 447 ms / 2,000 ms |
コード長 | 3,214 bytes |
コンパイル時間 | 3,276 ms |
コンパイル使用メモリ | 143,624 KB |
実行使用メモリ | 42,688 KB |
最終ジャッジ日時 | 2024-10-18 03:08:36 |
合計ジャッジ時間 | 7,275 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 84 ms
42,596 KB |
testcase_01 | AC | 129 ms
42,688 KB |
testcase_02 | AC | 100 ms
42,404 KB |
testcase_03 | AC | 269 ms
42,612 KB |
testcase_04 | AC | 447 ms
42,600 KB |
testcase_05 | AC | 237 ms
42,556 KB |
testcase_06 | AC | 438 ms
42,668 KB |
testcase_07 | AC | 429 ms
42,496 KB |
testcase_08 | AC | 446 ms
42,492 KB |
testcase_09 | AC | 436 ms
42,520 KB |
ソースコード
#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include <iostream> #include <atcoder/modint> using namespace std; using namespace atcoder; using mint = modint998244353; typedef long long ll; ll dp[110][110]; void bruteDp(int n,int m){ int i,j,k; dp[0][0] = 1; for(i=0;i<=n + m;i++){ for(j=0;j<=min(i,n);j++){ if(i==j && !j) continue; ll sum1 = 0,sum2 = 0; for(k=0;k<=i - 1;k++){ if(k<=n && (i - 1 - k)<=m) sum1 += dp[k][i - 1 - k]; } for(k=0;k<=i - 2;k++){ if(k<=n && (i - 2 - k)<=m) sum2 += dp[k][i - 2 - k]; } dp[j][i - j] += sum1; if(j>=1 && i - j>=1) dp[j][i - j] += sum1; if(j>=1 && i - j>=1) dp[j][i - j] += sum2; } } } ll dp2[110]; void bruteDp2(int n,int m){ int i; dp2[0] = 1; dp2[1] = 2; for(i=2;i<=n + m;i++){ if(i<=n){ dp2[i] = 2*i*dp2[i - 1] + (i - 1)*dp2[i - 2]; }else if(i<=m){ dp2[i] = (2*n + 1)*dp2[i - 1] + n*dp2[i - 2]; }else{ dp2[i] = 2*(n + m + 1 - i)*dp2[i - 1] + (n + m + 1 - i)*dp2[i - 2]; } } } #include <vector> #include <atcoder/convolution> mint BostanMori(vector<mint> P,vector<mint> Q,ll N){ while(N){ vector<mint> _Q(Q.size()); for(int i=0;i<Q.size();i++) _Q[i] = i&1 ? -Q[i] : Q[i]; vector<mint> nP = convolution(P,_Q); vector<mint> nQ = convolution(Q,_Q); Q.resize(nQ.size()/2 + 1); for(int i=0;i<nQ.size();i+=2) Q[i/2] = nQ[i]; if(N&1){ P.resize(nP.size()/2); for(int i=1;i<nP.size();i+=2) P[i/2] = nP[i]; }else{ P.resize((nP.size() + 1)/2); for(int i=0;i<nP.size();i+=2) P[i/2] = nP[i]; } N /= 2; } return P[0]/Q[0]; } const int MX = 10000000; mint f[MX + 10]; int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); f[0] = 1; f[1] = 2; for(int i=2;i<=MX;i++) f[i] = 2*i*f[i - 1] + (i - 1)*f[i - 2]; int t; cin >> t; while(t){ t--; ll i,j,n,m; cin >> n >> m; if(n>m) swap(n,m); if(n==0){ cout << 1 << "\n"; continue; } // f[n - 1],f[n],f[n + 1],...,f[m - 1],f[m]という数列のf[m - 1]とf[m]を求める vector<mint> P = {f[n - 1],f[n] - f[n - 1]*(2*n + 1)}; vector<mint> Q = {1,-2*n - 1,-n}; mint fm = BostanMori(P,Q,m - n + 1); mint gm = BostanMori(P,Q,m - n); // f[m - 1]→f[m + 1] (=f[n - 1]),f[m]→f[m + 1] or f[m + 2](=f[n - 2]) mint ans = gm*f[n - 1]*n + fm*f[n - 1]*2*n + (n>=2 ? fm*f[n - 2]*(n - 1) : 0); // bruteDp(n,m); bruteDp2(n,m); // for(i=0;i<=n + m;i++){ // int sum = 0; // for(j=max(0,i - m);j<=min(i,n);j++){ // cout << dp[j][i - j] << " "; // sum += dp[j][i - j]; // } // cout << "sum == " << sum; // cout << "\n"; // } // for(i=0;i<=n + m;i++) cout << dp2[i] << " "; // cout << "\n"; cout << ans.val() << "\n"; } }