BZOJ 3622(已经没有什么好害怕的了-Dp+容斥原理)

3622: 已经没有什么好害怕的了

Time Limit: 10 Sec  Memory Limit: 256 MB

Submit: 7  Solved: 6

[Submit][Status]

Description

Input

Output

Sample Input

4 2

5 35 15 45

40 20 10 30

Sample Output

4

HINT

Source

2014湖北省队互测week2

PS:本题的数据中能量互不相同。

1.我们计算出糖果>药片的组数=k

2.我们计算出f[i][j],表示到第i个糖果,糖果>药片的组数为j,且剩下无规定的情况数

(eg:a1>b1,a3>b3,a2不明;

a1>b1,a2>b2,a3不明)

△:此时有重合的情况(如上例),故接下来用容斥。

3.我们计算出f‘[i][j],表示到第i个糖果,糖果>药片的组数为j,且剩下的为糖果<药片的情况数。

显然有

其中(n-i)!表示剩下的全排列方案数

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForDk(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000009)
#define MAXN (2000+10)
#define MAXK (2000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n,k;
ll f[MAXN][MAXK]={0},C[MAXN][MAXN],jc[MAXN];
int a[2][MAXN]={0},l[MAXN]; //第i组第j个 

int main()
{
//	freopen("bzoj3622.in","r",stdin);
	scanf("%d%d",&n,&k);
	Rep(i,2) For(j,n) scanf("%d",&a[i][j]);
	sort((int*)a+1,(int*)a+1+n);
	sort((int*)a[1]+1,(int*)a[1]+1+n);
	if ((n+k)&1) {printf("0\n");return 0;}
	else k=(n+k)/2;
	/*
	Rep(i,2)
	{
		For(j,n)
		{
			printf("%d ",a[i][j]);
		}
		cout<<endl;
	}
	*/
	C[0][0]=1;
	For(i,n)
	{
		C[i][0]=C[i][i]=1;
		For(j,i-1) C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	}
	/*
	Rep(i,n+1)
	{
		Rep(j,i+1) cout<<C[i][j]<<' ';
		cout<<endl;
	}
	*/
//	cout<<k<<endl;
	int p=0;
	For(i,n)
	{
		while (p<n&&a[1][p+1]<a[0][i]) p++;
		l[i]=p;
	}

//	For(i,n) cout<<l[i]<<' ';cout<<endl;

	f[0][0]=1;
	For(i,n)
		Rep(j,/*min(i,k)+1*/i+1)
		{
			f[i][j]=f[i-1][j];
			if (j>0&&l[i]-(j-1)>0) f[i][j]=add(f[i][j],mul(f[i-1][j-1],l[i]-(j-1)));
		}

	jc[0]=1;For(i,n) jc[i]=mul(jc[i-1],i);
//	For(i,n) cout<<jc[i]<<' ';cout<<endl;

	ForDk(i,k/*1*/,n)
	{
		f[n][i]=mul(f[n][i],jc[n-i]);
		Fork(j,i+1,n) f[n][i]=sub(f[n][i],mul(f[n][j],C[j][i]));
	}

	/*
	For(i,n)
	{
		Rep(j,min(i,k)+1) cout<<f[i][j]<<' ';
		cout<<endl;
	}
	*/
	cout<<f[n][k]<<endl;

	return 0;
}

BZOJ 3622(已经没有什么好害怕的了-Dp+容斥原理),布布扣,bubuko.com

时间: 2024-10-27 09:07:02

BZOJ 3622(已经没有什么好害怕的了-Dp+容斥原理)的相关文章

BZOJ 3622 已经没有什么好害怕的了 动态规划+容斥原理

题目大意:给定两个长度为n个序列,保证这2n个数字两两不同,求有多少匹配满足a[i]>b[i]的数对数比a[i]<b[i]的数对数多k もう何も怖くない 题解:http://www.cnblogs.com/dyllalala/p/3900077.html OTZ 神思路根本就是想不到啊QAQ でも...もう何も怖くない...(大雾 此外我们可以引入一下WTY公式: C[i][j]=C[i-1][j]*C[i-1][j-1] ...脑残怎么治啊... #include <cstdio>

[BZOJ 3622]已经没有什么好害怕的了

世萌萌王都拿到了,已经没有什么好害怕的了——    (作死) 笑看哪里都有学姐,真是不知说什么好喵~ 话说此题是不是输 0 能骗不少分啊,不然若学姐赢了,那么有头的学姐还能叫学姐吗?  (作大死) 这题的数据就告诉我们这是赤裸裸的 dp ,不过要加个容斥而已 注意到我们可以算出一共需要 s 组满足糖果数 > 药片数 (在这里显然有个特判,即 n-k 为奇数时,答案一定为 0 ) 我们将两个读入的数组排序 令 next[i] 表示最大的 j 满足 糖果[i]>药片[j] 令 f[i][j] 表示

[BZOJ 3622]已经没有什么好害怕的了(Dp+容斥原理)

Description 图片略 Solution 对啊,已经没有什么好害怕的了 没有头的麻美学姐还是很萌的(雾 排序预处理p[i]为b中小于a[i]的最大的数的标号 f[i][j]表示前i个糖果使得糖果大于药片的至少有j组 则f[i][j]=f[i-1][j]+f[i-1][j-1]*(p[i]-j+1) 容斥得g[j]=f[n][j]*(n-j)!-∑g[k]*C(j,k) (j+1<=k<=n) #include<iostream> #include<cstdio>

[BZOJ 3622] 已经没有什么好害怕的了 手动反演

题意 给定两个大小为 n 的集合 A = {a[1], a[2], ..., a[n]} , B = {b[1], b[2], ..., b[n]} , 元素两两不同. 定义 L(A) 为 A 生成的排列的集合. 给定 K , 求 $\sum_{X \in L(A), Y \in L(B)} [\sum_{k = 1} ^ n [X_k > Y_k] - \sum_{k = 1} ^ n [X_k < Y_k] = K]$ . 1 <= n <= 2000, 0 <= K &

bzoj 3622 DP + 容斥

LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[i]大于b的组数. 不妨从整体去考虑,使用$f[n][j]$代表前n个中有j组$a[i]>b[i]$,很容易得到转移式$f[n][j]=f[n-1][j]+f[n-1][j-1]*(cnt[n]-(j-1))$,其中$cnt[i]$为比a[i]小的b[]个数 但是仔细思考该式子含义会发现,$f[n][j

BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)

Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<

【bzoj 3622】已经没有什么好害怕的了

题目 看到这个数据范围就发现我们需要一个\(O(n^2)\)的做法了,那大概率是\(dp\)了 看到恰好\(k\)个我们就知道这基本是个容斥了 首先解方程发现我们需要使得\(a>b\)的恰好有\(\frac{n+k}{2}\)组 如果不整除我们直接输出\(0\)就好了 之后开始使用套路,直接广义容斥 \[ans=\sum_{i=k}^n(-1)^{i-k}\binom{i}{k}g_i\] \(g_i\)表配出至少\(i\)对\(a>b\)的情况 显然我们现在需要一个\(dp\)来算一下\(g

bzoj 3622

直接算 $a_i>b_i$ 对数恰为 $k$ 的不好算 那么可以先算 $a_i>b_i$ 对数至少 $k$ 的 这个排序后随便dp一下就好 那么再除了一下 用 $f_i$ 表示 $a_i>b_i$ 对数至少i的方案数 用 $g_i$ 表示 $a_i>b_i$ 对数恰为i的方案数 那么 $g_i=f_i(n-i)!-\sum_{j=i+1}^n g_jC(j,i)$ 其中,$(n-i)!$ 表示除了这 $i$ 个以外的所有元素的排列方式,$g_jC(j,i)$ 表示在 $j$ 个中任

[BZOJ 2004] [Hnoi2010] Bus 公交线路 【状压DP + 矩阵乘法】

题目链接: BZOJ - 2004 题目分析 看到题目完全不会..于是立即看神犇们的题解. 由于 p<=10 ,所以想到是使用状压.将每个连续的 p 个位置压缩成一个 p 位 2 进制数,其中共有 k 位是1,表示这 k 个位置是某辆 Bus 当前停下的位置.需要注意的是,每个状态的第一位必须是 1 ,这样保证了不会有重复的状态. 每个状态可以转移到右边的某些状态(由当前状态的第一个 1 移动).初始状态和终止状态都是前面 k 位是 1 .用矩阵转移 n - k 次. 代码 #include <