校内省选比赛D2

(⊙o⊙)…今天有点迷啊

T1

在这里插入图片描述

  • emm。首先p=1,可以直接 n m n*m 递推,都会吧。有20分。
  • 再来考虑 p ! = 1 p!=1 的情况。因为 f [ i ] [ j ] = f [ i 1 ] [ j 1 ] b + f [ i 1 ] [ j ] a f[i][j]=f[i-1][j-1]*b+f[i-1][j]*a ,所以我们可以一列一列把所有答案求出来,即 n m n*m 预处理, O ( 1 ) O(1) 求。40分get。
  • 还是p=1的情况,此时 n , m < = 500000 n,m<=500000 。因此我们需要转换思路。画一个图,给某一行的每一列分别设定一个变量。递推表示一下,你发现,每一个 f [ 1 ] [ i ] f[1][i] f [ x ] [ y ] f[x][y] 的贡献,即是 f [ 1 ] [ i ] f[1][i] 本身乘上一个组合数,再乘上一个a的幂次和b的幂次。至于组合数具体是多少呢?很容易推出来,组合数是到达当前点的方案数吧,从上向下走,显然只有斜着走和正下方走,那么组合数为 C x 1 y i C_{x-1}^{y-i} 。b的幂次即为斜着走的步数,显然为 y i y-i ,那么a就是 x 1 y + i x-1-y+i 啦。okk,60分get。
  • 100分的做法需要我们推一下,当x在p上面时,怎么算。考虑,假设我们要求 f ( x , y ) f(x,y) ,它等于 f ( x + 1 , y ) f ( x , y 1 ) b a \frac{f(x+1,y)-f(x,y-1)*b}{a} 。这其实又变成了一个可以递推的式子,不断分解 f ( x + 1 , y ) f ( x , y 1 ) f(x+1,y)和f(x,y-1) 。直到 x = p x=p 停止。这仍然是一个组合数,只不过有正负区别。写一写,显然当列之间距离为奇数时,系数为负。否则为正。因为这次走法不同,只能向左或者向下,所以组合数是 C p x + y i 1 p x 1 C_{p-x+y-i-1}^{p-x-1} ,减1是因为最后一行不能向左走。从式子中可以看出,b仍然是需要乘的,但是a需要除。b的幂还是 y i y-i ,a的幂变成 p x + y i p-x+y-i 。okk。
    p > x , f [ x ] [ y ] = i = 1 y f [ p ] [ i ] C p x + y i 1 p x 1 b y i a p x + y i p>x,f[x][y]=\sum_{i=1}^{y}\frac{f[p][i]*C_{p-x+y-i-1}^{p-x-1}*b^{y-i}}{a^{p-x+y-i}}
    p < x , f [ x ] [ y ] = i = 1 y f [ p ] [ i ] C x p y i a x p y + i b y i p<x,f[x][y]=\sum_{i=1}^{y}f[p][i]*C_{x-p}{y-i}*a^{x-p-y+i}*b^{y-i}

Coding

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=15e6+100;
const ll mod=998244353;
ll n,m,a,b,p,q,jie[N],njie[N],inv[N],f[N],posa[N],posb[N];
ll read(){
	char ch=getchar();ll num=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
	return num*f;
}
void work(){
	inv[1]=1;
	for(ll i=2;i<=n+m;++i){
		ll x=-(ll)(mod/i)*inv[mod%i]%mod;
		inv[i]=(x+mod)%mod;
	}
	jie[0]=njie[0]=1;
	for(ll i=1;i<=n+m;++i) jie[i]=(ll)jie[i-1]*i%mod,njie[i]=(ll)njie[i-1]*inv[i]%mod;
	posa[0]=posb[0]=1;
	for(ll i=1;i<=n+m;++i) posa[i]=(ll)posa[i-1]*a%mod,posb[i]=(ll)posb[i-1]*b%mod;
}
ll power(ll a,ll b){
	ll res=1%mod;
	for(;b;b>>=1){ 
		if(b&1) res=(ll)res*a%mod;
		a=(ll)a*a%mod;
	}
	return res;
}
int main(){
	freopen("table.in","r",stdin);
	freopen("table.out","w",stdout);
	n=read(),m=read(),a=read(),b=read(),p=read(),q=read();
	for(ll i=1;i<=m;++i) f[i]=read();
	work();
	while(q--){
		ll x=read(),y=read();
		if(x==p) printf("%d\n",f[y]);
		else if(x>p){
			ll res=0;
			for(ll i=1;i<=y;++i){
				ll c;
				if(x-p<y-i) c=0;
				else c=jie[x-p]*njie[y-i]%mod*njie[x-p-y+i]%mod;
				res+=(ll)f[i]*posa[x-p-y+i]%mod*posb[y-i]%mod*c%mod;
				res=(res+mod)%mod;
			}
			printf("%lld\n",res);
		}else if(x<p){
			ll res=0;
			for(ll i=1;i<=y;++i){
				ll c;
				if(p-x+y-i<p-x) c=0;
				else c=jie[p-x+y-i-1]*njie[p-x-1]%mod*njie[y-i]%mod;
				if((y-i)%2==1) res-=(ll)f[i]*posb[y-i]%mod*c%mod*power(posa[y-i+p-x],mod-2)%mod;
				else res+=(ll)f[i]*posb[y-i]%mod*c%mod*power(posa[y-i+p-x],mod-2)%mod;
				res=(res+mod)%mod;
			}
			printf("%lld\n",res);
		}
	}
	return 0;
}

T2与T3,神仙题,咕咕咕

猜你喜欢

转载自blog.csdn.net/qq_39759315/article/details/88698532
d2