CF1251F题解

很容易看出来答案之和红板子的高度以及白板子的数量有关系。。。

看到 \(k\leq 5\) 所以直接考虑枚举红板子。

然后注意到,同样长度的板子超过 \(2\) 无所谓,所以分为三类讨论:没有,有一个,有两个以上。

没有的情况对答案的贡献是 \(1\),有一个的话可以放到左边或者右边,贡献为 \(2\),两个以上可以只拿一个出来,也可以左边右边各一个。

设某种长度的白板子有 \(c_kk\) 个,那么其贡献函数 \(F_c(x)=(1+2x+x^2)\bmod{x^{k+1}}\)

那么要求的多项式就是 \(G(x)=\prod_{c<b}F_c(x)\),然后求 \(2(\sum g_i\times(b+i+1))\)

先对红白板子的长度排序,然后统计前缀有 \(1\) 个和不小于 \(2\) 个板子的数量。假设分别是 \(a\)\(b\),那么计算一个 \((1+2x)^a(1+x)^{2b}\) 即可。显然可以做到 \(O(kn\log n)\)

然后。。。这东西是可以列 ODE 算的。。。

\(F(x)=(1+x)^a(1+2x)^b\),直接求导:

\[F'(x)=a(1+x)^{a-1}(1+2x)^{b}+2b(1+x)^{a}(1+2x)^{b-1} \]

\[(1+3x+2x^2)F'(x)=(a+2ax)F(x)+(2b+2bx)F(x) \]

\[(1+3x+2x^2)F'(x)=(a+2b+(2a+2b)x)F(x) \]

\[(n+1)\times f[n+1]+3n\times f[n]+(2n-2)\times f[n-1]=(a+2b)\times f[n]+(2a+2b)\times f[n-1] \]

\[n\times f[n]+(3n-3)\times f[n-1]+(2n-4)\times f[n-2]=(a+2b)\times f[n-1]+(2a+2b)\times f[n-2] \]

\[f[n]=\frac{1}{n}((a+2b-3n+3)\times f[n-1]+(4+2a+2b-2n)\times f[n-2]) \]

#include<algorithm>
#include<cstdio>
#include<cctype>
#define IMP(lim,act) for(int qwq=(lim),i=0;i^qwq;++i)act
const int M=1<<20|5,mod=998244353;
int n,k,ans[M<<1],x[M],y[10],a[10],b[10],inv[M];
inline int Getlen(const int&n){
	int len(0);while((1<<len)<n)++len;return len;
}
inline int pow(int a,int b=mod-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline void init(const int&n){
	inv[0]=inv[1]=1;for(int i=2;i<n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
inline void Get(int*f,const int&a,const int&b){
	const int&n=a+b+1;f[0]=1;f[1]=(a+b*2)%mod;
	for(int i=2;i<n;++i){
		f[i]=1ll*((a+2ll*b+(mod-3ll)*i+3)%mod*f[i-1]+(4ll+2*a+2*b+(mod-2ll)*i)%mod*f[i-2])%mod*inv[i]%mod;
	}
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void write(int n){
	static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);putchar(10);
}
signed main(){
	n=read();k=read();for(int i=1;i<=n;++i)x[i]=read();for(int i=1;i<=k;++i)y[i]=read();
	init(n+1<<1);std::sort(x+1,x+n+1);std::sort(y+1,y+k+1);
	for(int id(1),sum(0),A(0),B(0),t=1;t<=k;++t){
		while(x[id]<y[t]&&id<=n){
			++sum;
			if(x[id]!=x[id+1]){
				if(sum==1)++A;else if(sum)++B;
				sum=0;
			}
			++id;
		}
		static int F[M];Get(F,B<<1,A);IMP(A+B*2+1,ans[i+y[t]+1<<1]=(ans[i+y[t]+1<<1]+F[i])%mod);
	}
	k=read();while(k--)write(ans[read()]);
}
posted @ 2022-07-04 14:16  Prean  阅读(13)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};