BZOJ3284 不等式

不等式

给定如下不等式组

\[∀1 ≤ i ≤ n, x_i ≤ t\\ \sum_{i=1}^m x_i ≤ S \]

给定 \(S,t, n, m\),求解数。

  • \(S ≤ 10^{18}\)

  • \(n ≤ m ≤ 10^9\)

  • \(t ≤ 10^9,n ⋅ t ≤ S\)

  • \(m − n ≤ 10^3\)

题解

仓鼠《杂题选讲》。

假如暴力枚举前\(n\)个变量的取值,令它们的和为\(X\),那么后面的变量方案数可以用组合数算出答案就是 \(\binom{S−X}{m−n}\)

\(\binom{S−X}{m−n}\) 展开成一个关于\(x\)\(m − n\)次多项式\(F(x)\)

那么只要对于每个\(0 ≤ k ≤ m − n\)\(k\),均计算出\(\sum_{∀1≤i≤n,x_i≤t}(x_1 +x_2 + ⋯ + x_n)^k\),然后代入到\(F(x)\)里面即可。

记一个长度为\(m − n + 1\)的向量\(G_l\),其中\(G_{l,k}\)表示的就是\(\sum_{∀1≤i≤l,x_i≤t}(x_1 +x_2 + ⋯ + x_l)^k\) ,不难发现由\(G_a\)\(G_b\)可以直接\(O( (m − n)^2)\)求出\(G_{a+b}\)。直接倍增算出\(G_n\)即可。

时间复杂度 \(O((m-n)^2\log n)\)

CO int N=1e3+10;
int fac[N],ifac[N];

IN int C(int n,int m){
	return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int lagrange(int n,int T){
	static int val[N];
	for(int i=1;i<=n+2;++i) val[i]=add(val[i-1],fpow(i,n));
	static int pre[N],suf[N];
	pre[0]=1;
	for(int i=1;i<=n+2;++i) pre[i]=mul(pre[i-1],T+mod-i);
	suf[n+3]=1;
	for(int i=n+2;i>=1;--i) suf[i]=mul(suf[i+1],T+mod-i);
	int ans=0;
	for(int i=1;i<=n+2;++i){
		int sum=mul(val[i],mul(pre[i-1],suf[i+1]));
		sum=mul(sum,mul(ifac[i-1],ifac[n+2-i]));
		ans=add(ans,(n+2-i)%2==0?sum:mod-sum);
	}
	return ans;
}
poly operator+(CO poly&a,CO poly&b){
	int n=a.size()-1;
	poly ans(n+1);
	for(int i=0;i<=n;++i)for(int j=0;j<=i;++j)
		ans[i]=add(ans[i],mul(C(i,j),mul(a[j],b[i-j])));
	return ans;
}
poly operator*(CO poly&a,CO poly&b){
	int n=a.size()-1,m=b.size()-1;
	poly ans(n+m+1);
	for(int i=0;i<=n;++i)for(int j=0;j<=m;++j)
		ans[i+j]=add(ans[i+j],mul(a[i],b[j]));
	return ans;
}

int main(){
	fac[0]=1;
	for(int i=1;i<N;++i) fac[i]=mul(fac[i-1],i);
	ifac[N-1]=fpow(fac[N-1],mod-2);
	for(int i=N-2;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
	
	int64 S=read<int64>();int T=read<int>();
	int n=read<int>(),m=read<int>()-n;
	poly g(m+1);
	for(int i=0;i<=m;++i) g[i]=lagrange(i,T);
	poly f(m+1);f[0]=1;
	for(;n;n>>=1,g=g+g) if(n&1) f=f+g;
	poly p={1};
	for(int i=0;i<m;++i) p=p*(poly){int((S-i)%mod),mod-1};
	int ans=0;
	for(int i=0;i<=m;++i) ans=add(ans,mul(p[i],f[i]));
	printf("%d\n",mul(ans,ifac[m]));
	return 0;
}

posted on 2020-03-24 11:15  autoint  阅读(201)  评论(0编辑  收藏  举报

导航