#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include #include 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 #include mint BostanMori(vector P,vector Q,ll N){ while(N){ vector _Q(Q.size()); for(int i=0;i nP = convolution(P,_Q); vector nQ = convolution(Q,_Q); Q.resize(nQ.size()/2 + 1); for(int i=0;i> 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 P = {f[n - 1],f[n] - f[n - 1]*(2*n + 1)}; vector 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"; } }