【BZOJ 3284】不等式

题目

这题太妙了,所以来写题解;

注意到题目中的两个重要条件,\(n\times t\leq S,m-n\leq 10^3\);于是\(\sum_{i=1}^n x_i\)一定不会超过\(S\);设这个和为\(N\),对于一个给定的\(N\),根据插板我们之后后面的方案数是\(\binom{S-N}{m-n}\)

众所周知,\(\binom{x}{y}\)是一个关于\(x\)\(y\)次多项式,所以\(\binom{S-N}{m-n}\)一定可以写成\(\sum_{i=0}^{m-n}f_i(S-N)^i\)的形式,\((S-N)^i\)可以根据二项式定理来展开,于是我们如果能对于\(k\in [0,m-n]\)求出每一种方案的\(N^k\)之和,即\(\sum_{1\leq x_i\leq t,i\leq n}(x_1+x_2+\dots +x_n)^k\)就能快速计算答案了。

显然可以倍增,用二项式定理合并答案,复杂度是\(O((m-n)^2\log n)\);其实也可以搞一个生成函数\(F(x)=\sum_{i=0}^{m-n}\frac{\sum_{j=1}^t j^i}{i!}x^i\),求\(F^n(x)\)即可,可以多项式exp,做到\(O((m-n)^2)\),但是由于我不会写暴力exp于是还是口胡一下就算了吧;

代码,只能在dark上过

#include<bits/stdc++.h>
#define re register
#define LL long long
const int mod=1e9+7,maxn=1e3+5;
inline int dqm(int x) {return x<0?x+mod:x;}
inline int qm(int x) {return x>=mod?x-mod:x;}
inline void upd(int &x,int y) {x+=y;if(x>=mod)x-=mod;}
inline int ksm(int a,int b) {
	int S=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)S=1ll*S*a%mod;return S;
}
LL Sum,lm;int n,m,ln,pre[maxn],pw[maxn],c[maxn][maxn];
int A[maxn],h[maxn],g[maxn],fac[maxn],ifac[maxn],__pw[maxn][maxn];
inline void Lagrange() {
	if(!ln){h[0]=1;return;}h[1]=1;
	for(re int i=1;i<ln;i++) 
		for(re int j=i;j>=0;j--) {
			upd(h[j+1],h[j]);
			h[j]=1ll*h[j]*(mod-i)%mod;
		}
	for(re int i=0;i<=ln;i++) h[i]=1ll*h[i]*ifac[ln]%mod; 
}
inline int calc(int n,int k) {
	for(re int i=0;i<=k+1;i++) pre[i]=__pw[i][k];
	for(re int i=1;i<=k+1;++i) upd(pre[i],pre[i-1]);
	if(n<=k+1) return dqm(pre[n]-(k==0));
	int prd=1,tot=0;
	for(re int i=0;i<=k+1;++i) prd=1ll*prd*dqm(n-i)%mod;
	for(re int i=0;i<=k+1;++i) {
		int v=1ll*prd*ksm(dqm(n-i),mod-2)%mod*pre[i]%mod;
		v=1ll*ifac[i]*v%mod*ifac[k+1-i]%mod;
		if((k+1-i)&1) v=dqm(-v);upd(tot,v);
	}
	return dqm(tot-(k==0));
}
inline void mul(int *B,int *C) {
	for(re int nw=0,i=ln;i>=0;B[i]=nw,--i,nw=0) 
		for(re int j=0;j<=i;++j)
			upd(nw,1ll*B[i-j]*C[j]%mod*c[i][j]%mod); 
}
void solve(int n,int *f) {
	if(n==1) {
		for(re int i=0;i<=ln;++i) g[i]=f[i]=calc(lm%mod,i);
		return;
	}
	solve(n>>1,f);mul(f,f);if(n&1)mul(f,g);
} 
int main() {
	scanf("%lld%lld%d%d",&Sum,&lm,&n,&m);
	ln=m-n+1;fac[0]=ifac[0]=1;
	for(re int i=1;i<=ln;++i)fac[i]=1ll*fac[i-1]*i%mod;
	ifac[ln]=ksm(fac[ln],mod-2);
	for(re int i=ln-1;i;i--)ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
	for(re int i=0;i<=ln;i++)__pw[i][0]=1,c[i][0]=c[i][i]=1;
	for(re int i=1;i<=ln;i++) 
		for(re int j=1;j<=ln;++j) __pw[i][j]=1ll*__pw[i][j-1]*i%mod;
	for(re int i=1;i<=ln;i++)
		for(re int j=1;j<i;++j) c[i][j]=qm(c[i-1][j]+c[i-1][j-1]);
	ln--;Lagrange();solve(n,A);int ans=0;Sum%=mod;
	pw[0]=1;for(re int i=1;i<=ln;i++)pw[i]=1ll*pw[i-1]*Sum%mod;
	for(re int i=0;i<=ln;++i) {
		int nw=0;
		for(re int j=0;j<=i;++j) 
			upd(nw,1ll*pw[i-j]*A[j]%mod*c[i][j]%mod*(j&1?mod-1:1)%mod);
		upd(ans,1ll*h[i]*nw%mod);
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2020-03-16 20:00  asuldb  阅读(239)  评论(0编辑  收藏  举报