$\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. idea如何搭建springmvc4

    1.推荐大牛博客 此操作我操作了三次过后终于成功了,奉献大牛博客连接:做的非常详细到位,望各位采纳,推荐置顶. https://www.cnblogs.com/chenlinghong/p/83395 ...

  2. vue数组操作不触发前端重新渲染

    暂时使用给数组先赋值 [ ] ,然后重新赋值的方式解决. 此外,能够监听的数组变异方法 https://cn.vuejs.org/v2/guide/list.html#%E5%8F%98%E5%BC% ...

  3. eCharts 多个图表自适应窗口大小

    单个图表自适应页面窗口只需要在创建图表节点后面添加一句代码就可以了: window.onresize = myChart.resize; 多图表要自适应页面,创建图表节点后面添加事件,并在事件函数里面 ...

  4. 关于Solaris系统“mpt_sas”驱动

    1.mpt_sas 驱动源文件所在系统源代码中目录: illumos-soulos/usr/src/uts/common/sys/scsi/adapters/mpt_sas  -- 头文件 illum ...

  5. poj 2253 Frogger (dijkstra最短路)

    题目链接:http://poj.org/problem?id=2253 Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissi ...

  6. ribbon设置url级别的超时时间

    序 ribbon的超时设置,只能按转发的serviceId来分的,无法像nginx那样直接在每个转发的链接里头设置超时时间.这里hack一下,实现url基本的ribbon超时时间设置.具体的思路就是重 ...

  7. Python脚本 - 查询磁盘的读写次数信息

    测试系统为:Centos 6.7 Python版本为: 3.6.4 脚本功能:查看指定磁盘的读写及时间等相关信息 #!/usr/bin/env python3 from collections imp ...

  8. 【Python学习笔记】Coursera课程《Using Python to Access Web Data 》 密歇根大学 Charles Severance——Week2 Regular Expressions课堂笔记

    Coursera课程<Using Python to Access Web Data > 密歇根大学 Charles Severance Week2 Regular Expressions ...

  9. tornado当用户输入的URL无效时转入设定的页面

    今天做web的测验..坑爹的要用tornado...作为一个比较新的用的人还不多的东东...查资料好麻烦.. 下面是当用户输入非法 url时, 显示一个自定义 404 页面提示用户,其访问的页面不存在 ...

  10. 【C++】C++11的auto和decltype关键字

    转自: http://www.linuxidc.com/Linux/2015-02/113568.htm 今天要介绍C++11中两个重要的关键字,即auto和decltype.实际上在C++98中,已 ...