题目传送门(内部题39)
输入格式
第一行:四个正整数$n$、$m$、$a$、$b$。
第二行:$n$个正整数,第$i$个表示$f(i,0)$。
第三行:$m$个正整数,第$i$个表示$f(0,i)$。
输出格式
第一行:一个整数,代表$f(n,m)\mod 998244353$。
样例
样例输入:
4 4 3 2
1 3 5 7
2 4 6 8
样例输出:
50807
数据范围与提示
$20\%$的数据:$n,m\leqslant 10,a,b\leqslant 3,f(i,0),f(0,i)\leqslant 10$。
$50\%$的数据:$n,m\leqslant {10}^3$。
另外$10\%$的数据:$n=1$。
另外$10\%$的数据:$a=b=1$。
另外$10\%$的数据:$f(i,0)=f(0,i)=1$。
$100\%$的数据:$n,m\leqslant 3\times {10}^5$,其他所有输入数据均在$long\ long$范围内。
题解
对于每一个点$(i,j)$,其到点$(n,m)$的向每个方向需要走的步数都是确定的,走法可以通过组合数计算。
于是点$(i,j)$对答案的贡献就是$f(i,j)\times$走法数$\times a^{m-i}\times b^{n-i}$。
预处理组合数,用快速幂统计答案即可。
时间复杂度:$\Theta(n\log n+m\log m)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> using namespace std; const long long mod=998244353; long long n,m; long long a,b; long long p[300010],q[300010]; long long fac[600010],inv[600010]; long long ans; long long qpow(long long x,long long y) { long long res=1; while(y) { if(y&1)res=res*x%mod; x=x*x%mod; y>>=1; } return res; } long long C(long long x,long long y){return 1LL*fac[x]*inv[x-y]%mod*inv[y]%mod;} int main() { scanf("%lld%lld%lld%lld",&n,&m,&a,&b); a=(a+mod)%mod; b=(b+mod)%mod; for(long long i=1;i<=n;i++){scanf("%lld",&p[i]);p[i]=(p[i]+mod)%mod;} for(long long i=1;i<=m;i++){scanf("%lld",&q[i]);q[i]=(q[i]+mod)%mod;} fac[0]=inv[0]=1; for(long long i=1;i<=n+m;i++) fac[i]=1LL*fac[i-1]*i%mod; inv[n+m]=qpow(fac[n+m],mod-2); for(long long i=n+m;i;i--) inv[i-1]=1LL*inv[i]*i%mod; for(long long i=1;i<=n;i++) ans=(ans+C(n+m-1-i,m-1)*qpow(a,m)%mod*qpow(b,n-i)%mod*p[i]%mod)%mod; for(long long i=1;i<=m;i++) ans=(ans+C(n+m-1-i,n-1)*qpow(b,n)%mod*qpow(a,m-i)%mod*q[i]%mod)%mod; printf("%lld",ans); return 0; }
rp++
原文地址:https://www.cnblogs.com/wzc521/p/11498454.html
时间: 2024-11-05 11:45:54