考虑第
p
p
行的每个数对询问的贡献。
对于
x>p
x
>
p
,观察
fi,j=afi−1,j+bfi−1,j−1,
f
i
,
j
=
a
f
i
−
1
,
j
+
b
f
i
−
1
,
j
−
1
,
每个
fp,i
f
p
,
i
相当于向下走一步并
×a
×
a
,或者向右下走一步并
×b
×
b
,再给路径条数计下数,就有
对于 x<p x < p ,把式子变形成 fi,j=1afi+1,j−bafi,j−1 f i , j = 1 a f i + 1 , j − b a f i , j − 1 ,相当于向上走一步并 ×1a × 1 a ,或者向右走一步并 ×(−ba) × ( − b a ) (且不能再第 p p 行),就有
复杂度 O(nq+m) O ( n q + m ) 。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 100010
#define M 10100010
#define up(x,y) (x=(x+(y))%mod)
using namespace std;
const int mod=998244353;
int m,n,a,b,p,q;
ll f[N],fac[M],ifac[M],pow_a[M],pow_b[M],ip_a[M];
int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*f;
}
ll ksm(ll a,int b){ll r=1;for(;b;b>>=1){if(b&1)r=r*a%mod;a=a*a%mod;}return r;}
ll C(int a,int b){return a<b?0:fac[a]*ifac[b]%mod*ifac[a-b]%mod;}
int main()
{
m=read();n=read();a=read();b=read();p=read();q=read();
for(int i=1;i<=n;i++)
f[i]=read();
fac[0]=1;
for(int i=1;i<=m+n;i++)
fac[i]=fac[i-1]*i%mod;
ifac[m+n]=ksm(fac[m+n],mod-2);
for(int i=m+n-1;i>=0;i--)
ifac[i]=ifac[i+1]*(i+1)%mod;
pow_a[0]=pow_b[0]=1;
for(int i=1;i<=m+n;i++)
pow_a[i]=pow_a[i-1]*a%mod,pow_b[i]=pow_b[i-1]*b%mod;
ip_a[1]=ksm(a,mod-2);
for(int i=2;i<=m+n;i++)
ip_a[i]=ip_a[i-1]*ip_a[1]%mod;
while(q--)
{
int x=read(),y=read();ll ans=0;
if(x>=p)
{
for(int k=max(0,y-x+p);k<=y;k++)
up(ans,C(x-p,y-k)*pow_b[y-k]%mod*pow_a[x-p-y+k]%mod*f[k]);
}
else
{
for(int k=y,v=1;k;k--,v=-v)
up(ans,C(p-x+y-k-1,y-k)*pow_b[y-k]%mod*ip_a[p-x+y-k]%mod*f[k]%mod*v+mod);
}
printf("%lld\n",ans);
}
return 0;
}