题目描述
C 酱有一个 m \times n m×n 的数表,行与列的编号都从 1 1 开始。令 f i,j
表示表格第 i i 行第 j j 列内的数,那么对于表格的第 i (i > 1) i(i>1) 行有
然而 C 酱已经把表格中的数忘得差不多了,他现在只记得第 p 行的数。他希望你能够帮忙还原出部分位置的数值。
输入格式
输入第一行为 66 个整数 m,n,a,b,p,q其中 q表示询问的个数。
接下来 qq 行,每行两个整数 x,yx,y,表示 C 酱询问你 fx,y的数值。
输出格式
输出共 qq 行,依次表示每个询问的答案在模 998244353 意义下的取值。
即设答案可以表示为分式 a/b ,则输出整数 x 使得 b \times x \equiv a \pmod {998244353}b×x≡a(mod998244353) 且 0 \leqslant x < 9982443530⩽x<998244353。可以证明这样的整数 x 是唯一的。
样例
样例输入 1
5 4 1 1 3 5
1 0 0 0
5 2
3 1
1 2
2 3
4 3
样例输出 1
2
1
998244351
1
0
样例输入 2
10 5 233 2333 6 4
9 3 1 0 10
1 5
10 2
5 3
8 1
样例输出 2
110343631
118211750
770559638
488601
数据范围与提示
对于 100%100% 的数据,保证 1 \leq q \leq 100 , 1 \leq x , p \leq m , 1 \leq y \leq n , 1 \leq a,b < 998244353,0 \leq f_{i,j} < 9982443531≤q≤100,1≤x,p≤m,1≤y≤n,1≤a,b<998244353,0≤f i,j <998244353。
来源
2018年3月雅礼集训
题解:
首先,对于在p行下方的点,我们可以计算p行的每个点对于该点的贡献。
由于公式
可知可以等价为每个点可以乘a向下走,或者乘b向右下走。
在计算时就可以采用组合计数。
再者,对于在p行上方的点,我们也可以同理,不过公式应该变形为
f[i][j]=1/a* f[i+1][j]-b/a*f[i][j-1];
此时等价于每个点可以向上除a,或向右乘b除a。
注意:
计算乘法逆元时可以倒着/正着递推,省时
向上计算时注意总步数因为p-x+y-i+1,向上走的步数是p-x-1。(emm我也不太清楚为什么)
感谢@jacky大佬修改查错。orz orz
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 100005+10000005
using namespace std;
const long long mod=998244353;
long long n,m,a,b,p,q;
long long a_sqrt[N],b_sqrt[N];
long long jcinva[N],jcinvb[N];
long long f[N];
long long cc[N],jcinvcc[N];
long long power(long long x,long long b){
long long c=x,ans=1;
while(b){
if(b&1)ans=(ans*c)%mod;
c=(c*c)%mod;b>>=1;
}
//return ans%mod;
return ans;
}
int main()
{
cin>>m>>n>>a>>b>>p>>q;
for(int i=1;i<=n;i++){
cin>>f[i];
}
cc[0]=1;jcinvcc[0]=1;
a_sqrt[0]=jcinva[0]=1;
b_sqrt[0]=jcinvb[0]=1;
int inva=power(a,mod-2);
for(int i=1;i<=n+m;i++){
a_sqrt[i]=(a_sqrt[i-1]*a)%mod;
jcinva[i]=(jcinva[i-1]*inva)%mod;
b_sqrt[i]=(b_sqrt[i-1]*b)%mod;
//jcinvb[i]=(jcinvb[i-1]*power(b,mod-2))%mod;
jcinvb[i]=(jcinvb[i-1]*(mod-b*inva%mod))%mod;
cc[i]=(cc[i-1]*i)%mod;
//jcinvcc[i]=power(cc[i],mod-2);
//cout<<b_sqrt[i]<<" "<<jcinvb[i]<<endl;
}
jcinvcc[n+m]=power(cc[n+m],mod-2);
for(int i=n+m-1;i>=0;i--) jcinvcc[i]=(jcinvcc[i+1]*(i+1))%mod;
for(int g=1;g<=q;g++){
int x,y;cin>>x>>y;
long long ans=0;
if(x==p){cout<<f[y]<<endl;continue;}
if(x>p){
for(int i=1;i<=y;i++){
if(x-p<y-i)continue;
ans+=(f[i]%mod*cc[x-p]%mod*jcinvcc[y-i]%mod*jcinvcc[x-p-y+i]%mod*a_sqrt[x-p-y+i]
%mod*b_sqrt[y-i]%mod);
ans%=mod;
}
//cout<<(ans+mod)%mod<<endl;
cout<<ans<<endl;
}else{
for(int i=1;i<=y;i++){
//long long now=1;
//now*=(f[i]%mod*cc[p-x+y-i-1]%mod)%mod;now=(now%mod+mod)%mod;
//now*=(jcinvcc[p-x-1]%mod*jcinvcc[y-i]%mod)%mod;now=(now%mod+mod)%mod;
//now*=(jcinva[p-x+y-i]%mod*b_sqrt[y-i]%mod)%mod;now=(now%mod+mod)%mod;
//now*=power(-1,y-i);now=(now%mod+mod)%mod;
//ans=ans+now;
//ans=((ans+now)%mod+mod)%mod;
//cout<<f[i]<<" "<<cc[p-x+y-i]<<" "<<jcinvcc[p-x]<<" "<<jcinvcc[y-i]<<" "<<jcinva[p-x]
//<<" "<<b_sqrt[y-i]<<" "<<jcinva[y-i]<<" "<<power(-1,y-i)<<endl;
ans=(ans+f[i]*cc[p-x+y-i-1]%mod*jcinvcc[p-x-1]%mod*jcinvcc[y-i]%mod*jcinva[p-x]%mod*jcinvb[y-i]%mod)%mod;
ans=(ans+mod)%mod;
}
cout<<ans<<endl;
}
}
//cout<<power(-1,1)<<endl;
return 0;
}
/*
10 5 233 2333 6 4
9 3 1 0 10
1 5
10 2
5 3
8 1
*/
/*
5 4 1 1 3 5
1 0 0 0
5 2
3 1
1 2
2 3
4 3
*/