$\newcommand{stirf}[2]{{{#1}\brack{#2}}}$$\newcommand{stirs}[2]{{{#1}\brace{#2}}}$题意:$\sum\limits_{i=1}^mx_i\leq s$,对$\forall1\leq i\leq n,x_i\leq t$,求这个方程组的解数

做了几天总算是弄明白了...

会用到$\sum\limits_{k\leq n}\binom km=\binom{n+1}{m+1}$,这个直接归纳可证

方程$\sum\limits_{i=1}^nx_i=s,x_i\geq1$的解数是$\binom{s-1}{n-1}$,所以$\sum\limits_{i=1}^nx_i\leq s,x_i\geq1$的解数是$\binom sn$

枚举$x_{1\cdots n}$,答案即为$\sum\limits_{1\leq x_1\leq t}\cdots\sum\limits_{1\leq x_n\leq t}\binom{s-\sum\limits_{i=1}^n x_i}{m-n}$

如果去掉$\leq t$的限制,那么答案显然是$\binom sm$

所以对原问题考虑容斥,枚举至少有$k$个$x_i$不满足$x_i\leq t$的限制,将这些$x_i$减去$t$后就将限制变成了$1\leq x_i$,那么答案为$\sum\limits_{k=0}^n(-1)^k\binom nk\binom{s-kt}m$

接下来是构造,对于一个函数$f(x)$,对其$n$阶差分的结果为$\Delta^nf(x)=\sum\limits_{k=0}^n(-1)^{n+k}\binom nkf(x+k)$,令$f(x)=\binom{s-xt}m$,那么答案为$(-1)^n\Delta^nf(0)$

$f(x)$是一个$m$次多项式,写出它的牛顿级数$\sum\limits_{i=0}^mb_i\binom xi$并将其代入差分式中

$\begin{aligned}\Delta^nf(0)&=\sum\limits_{k=0}^n(-1)^{n+k}\binom nkf(k)\\&=\sum\limits_{k=0}^n(-1)^{n+k}\binom nk\sum\limits_{i=0}^mb_i\binom ki\\&=\sum\limits_{i=0}^mb_i\sum\limits_{k=0}^n(-1)^{n+k}\binom nk\binom ki\\&=\sum\limits_{i=0}^mb_i\binom ni(-1)^{n-i}\sum\limits_{k=0}^n(-1)^{k-i}\binom{n-i}{k-i}\\&=\sum\limits_{i=0}^mb_i\binom ni(-1)^{n-i}[n=i]\\&=b_n\end{aligned}$

所以我们只需求$b_n$,但为了求$b_n$,我们要先求$f(x)=\sum\limits_{i=0}^ma_ix^i$中的$a_i$,直接把下降幂展开成斯特林数即可,我们得到$a_i=\frac1{m!}\sum\limits_{j=i}^m(-1)^{m+i+j}\binom ji\stirf mjt^is^{j-i}$

$\begin{aligned}f(x)&=\sum\limits_{i=0}^ma_ix^i\\&=\sum\limits_{i=0}^ma_i\sum\limits_{j=0}^i\stirs ijx^{\underline j}\\&=\sum\limits_{j=0}^m\binom xj\sum\limits_{i=j}^ma_i\stirs ijj!\end{aligned}$

于是$b_n=\frac{n!(-1)^mt^n}{m!}\sum\limits_{i=0}^{m-n}\sum\limits_{j=0}^{m-n-i}(-1)^j\binom{n+i+j}j\stirs{n+i}n\stirf m{n+i+j}t^is^j$

差不多结束了,最后有一个小问题:求斯特林数

要求$\stirs nm$,虽然$n,m$都非常大,但$n-m$非常小,考虑$\stirs nm$的组合意义:将$n$个元素分为$m$个非空子集,因为最多有$n-m$个子集中的元素个数$\gt1$,设$g(n,m)$表示将$n$个元素分成$m$个子集,使得每个子集包含元素个数都$\gt1$的方案数,那么枚举$m$个子集中元素个数$\gt1$的子集个数$k$(剩下$m-k$个集合都只包含一个元素),我们得到$\stirs nm=\sum\limits_{k=0}^{n-m}\binom n{m-k}g(n-m+k,k)$

$g$的递推就和第二类斯特林数差不多了:$g(n,m)=m\cdot g(n-1,m)+(n-1)g(n-2,m-1)$

第一类也是类似的,只不过$g$的递推要相应地改成$g(n,m)=(n-1)g(n-1,m)+(n-1)g(n-2,m-1)$

于是我们可以$O\left((m-n)^2\right)$预处理并$O(m-n)$计算单个斯特林数,总的时间复杂度就是$O\left((m-n)^2\right)$了

数学真是一门化腐朽为神奇的学科==

#include<stdio.h>
typedef long long ll;
const int mod=1000000007;
int mul(int a,int b){return(ll)a*b%mod;}
int ad(int a,int b){return(a+b)%mod;}
void inc(int&a,int b){(a+=b)%=mod;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
int g1[210][210],g2[210][210],fac[210],rfac[210],inv[210];
void pre(int n){
	int i,j;
	g1[0][0]=g2[0][0]=1;
	for(i=1;i<=n;i++){
		for(j=1;j*2<=i;j++){
			g1[i][j]=mul(i-1,g1[i-1][j]);
			g2[i][j]=mul(j,g2[i-1][j]);
			if(i>1){
				inc(g1[i][j],mul(i-1,g1[i-2][j-1]));
				inc(g2[i][j],mul(i-1,g2[i-2][j-1]));
			}
		}
	}
	fac[0]=1;
	for(i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	rfac[n]=pow(fac[n],mod-2);
	for(i=n;i>0;i--)rfac[i-1]=mul(rfac[i],i);
	inv[1]=1;
	for(i=2;i<=n;i++)inv[i]=-mul(mod/i,inv[mod%i]);
}
int binom(int n,int k){//k is small
	int i,s=1;
	for(i=0;i<k;i++)s=mul(s,n-i);
	return mul(s,rfac[k]);
}
int stirf(int n,int m){
	int i,t,s,b;
	s=0;
	b=binom(n,n-m);
	for(i=0;i<=n-m;i++){
		t=n-m+i;
		inc(s,mul(b,g1[t][i]));
		b=mul(b,mul(n-t,inv[t+1]));
	}
	return s;
}
int stirs(int n,int m){
	int i,t,s,b;
	s=0;
	b=binom(n,n-m);
	for(i=0;i<=n-m;i++){
		t=n-m+i;
		inc(s,mul(b,g2[t][i]));
		b=mul(b,mul(n-t,inv[t+1]));
	}
	return s;
}
int a[110],b[110];
class TrickyInequality{
	public:
		int countSolutions(ll s,int t,int n,int m){
			int i,j,res,pt,ps,bi;
			s%=mod;
			pre(200);
			for(i=0;i<=m-n;i++){
				a[i]=stirf(m,n+i);
				b[i]=stirs(n+i,n);
			}
			res=0;
			pt=1;
			for(i=0;i<=m-n;i++){
				ps=1;
				bi=1;
				for(j=0;j<=m-n-i;j++){
					inc(res,(j&1?-1:1)*mul(mul(mul(bi,b[i]),a[i+j]),mul(pt,ps)));
					ps=mul(ps,s);
					bi=mul(bi,mul(n+i+j+1,inv[j+1]));
				}
				pt=mul(pt,t);
			}
			res=mul(res,pow(t,n));
			for(i=n+1;i<=m;i++)res=mul(res,pow(i,mod-2));
			if((n+m)&1)res=-res;
			return(res+mod)%mod;
		}
};
/*
int main(){
	ll s;
	int t,n,m;
	TrickyInequality cl;
	scanf("%I64d%d%d%d",&s,&t,&n,&m);
	printf("%d",cl.countSolutions(s,t,n,m));
}
*/

[TCO2013]TrickyInequality的更多相关文章

  1. @topcoder - 2013TCO3A D1L3@ TrickyInequality

    目录 @description@ @accepted code@ @accepted code@ @details@ @description@ 现有不等式组: \[\begin{cases} x_1 ...

  2. [TCO2013]Block3Checkers

    题意:一个网格上有一些障碍和$3$个在网格边界上的棋子,你要添加一些障碍使得没有两个棋子四连通,问最少添加多少个障碍 官方题解——一张图教你做人... 三个棋子将网格边界分成三段,添加障碍后网格中一定 ...

  3. [TCO2013]LitPanels

    题意:一个$n\times m$的无色网格,你可以在其中选择两个$x\times y$的子矩形并在其中将其中任意的格子涂上颜色,问最终能得到多少种不同的网格 做这题会用到一个概念叫包围盒(boundi ...

  4. [TCO2013]DirectionBoard

    题意:给一个网格,每个格子有一个方向表示在这个格子上要往哪个方向走,你可以改变某些格子的方向,问最少多少次操作使得从任意格子出发都能回到这个格子 woc这都不会我还是回家种田去吧... 题目的要求是改 ...

随机推荐

  1. 大聊Python----通过Socket实现简单的ssh客户端

    光只是简单的发消息.收消息没意思,干点正事,可以做一个极简版的ssh,就是客户端连接上服务器后,让服务器执行命令,并返回结果给客户端. #ssh_client.py import socket cli ...

  2. js_数组去重效率对比

    学习javascript已经快两年了,也不知道到了什么程度了. 说说我对javascript的理解,在电脑的世界里,只有数据. 数组,对象,字符串.对这些数据进行操作就可以完成很多业务逻辑,和页面的交 ...

  3. jq_$.extend和$.fn.extend插件开发和方法的封装

    --------杂谈-------- 随着使用的使用js和jq使用的越来越娴熟,也就是说日常产品经理给的一些需求,已经在自己的能力范围内了.空出来了一点时间,来研究如何优化你的代码, 不管是性能上,还 ...

  4. Xmind 8 update5 破解

    Step 1. Download XMind Step 2. Run XMind at least once after installation, xmind will init the confi ...

  5. 蓝屏代码0X0000007B可能是SATA mode问题

    Win7蓝屏代码0X0000007B可能是硬盘模式的问题,我进入BIOS把SATA的mode从Enhanced改为Compatible(及IDE兼容模式)结果系统可以顺利启动没有问题.       从 ...

  6. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  7. 解决springmvc+fastjson返回页面出现乱码问题

    在controller里面的接口上面加,produces="text/html;charset=UTF-8"即可 @RequestMapping(value = "/ad ...

  8. Oralce Spatial

    1.建立数据库连接 create public database link ytlink connect to hightop identified by hightop using '(DESCRI ...

  9. 我的新博客地址http://xxxbw.github.io/

    最近在学github,在github搭了个博客,以后也会使用另外一个博客.有兴趣的小伙伴可以看看~ 地址:http://xxxbw.github.io/

  10. CF914F Substrings in a String

    Description 给你一个字符串ss,共有qq次操作,每个都是下面两种形式的一种. 11 ii cc 这个操作表示将字符串ss的第ii项变为字符cc 22 ll rr yy 这个操作表示输出字符 ...