zoukankan      html  css  js  c++  java
  • 题解-bzoj4221 JOI2012kangaroo

    Problem

    bzoj

    题意:给定(n)只袋鼠,每只袋鼠有俩属性(a,b),若(a_ileq b_j),则(i)是可以被(j)放置在袋子里的,求经过一系列放置操作后无法进行操作时的状态有多少种可能(每只袋鼠只能被一只袋鼠放在袋子里,同时也只能放一只袋鼠在袋子里)

    (nleq 300,forall iin[1,n]a_igeq b_i)

    Solution

    将每只袋鼠拆成出点和入点后做匹配,相当于剩余未匹配点中(min ageq max b)的匹配方案数

    由于(a_igeq b_i)保证不可能自己连向自己,相当于是自由匹配,所以点与点之间的顺序是没有任何关系的,考虑将两者从大到小排序

    (f[i][j][k])表示当前考虑到第(i)只袋鼠的体积,这(i)只袋鼠中有(j)只已经被匹配,设(t)为第(i)只袋鼠能塞进的最小口袋((t)也递增),则(k)表示前(t)个口袋中与袋鼠([i+1,n])中匹配的数量

    考虑到在定义下的(f[i][j][k])中,这(j)只已经被匹配的袋鼠所对应的口袋一定在区间([1,t])中,所以口袋([1,t])分为三类:

    • ① 和区间([1,i])内共(j)只袋鼠匹配的口袋,共(j)
    • ② 和区间([i+1,n])内共(k)只袋鼠匹配的口袋,共(k)
    • ③ 自由节点,尚未匹配,共(t-j-k)

    理顺了这些可以得到以下仨转移式(一般自己写可能会有情况缺漏,反正我是想了很久)

    [f[i][j][t-j]+=f[i-1][j][k] ]

    [f[i][j+1][k]+=f[i-1][j][k]cdot (t-j-k) ]

    [f[i][j+1][k-1]+=f[i-1][j][k]cdot k ]

    自然统计答案

    [Ans=sum_{i=0}^nf[n][i][0] ]

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define rg register
    
    template <typename _Tp> inline _Tp read(_Tp&x){
    	char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
    	while(isdigit(c11))x=x*10+c11-'0',c11=getchar();return x;
    }
    
    const int N=301,p=1e9+7;
    int f[N][N][N],a[N],b[N];
    int n,ans;
    
    template <typename _tp> inline void pls(int&A,_tp B){A=A+B<p?A+B:A+B-p;}
    inline bool cmp(const int&A,const int&B){return A>B;}
    
    void init();void work();void print();
    int main(){init();work();print();return 0;}
    
    void work(){
    	f[0][0][0]=1;
    	for(rg int i=1,t=1;i<=n;++i){
    		if(!t)++t;
    		while(a[i]<b[t]&&t<=n)++t;--t;
    		for(rg int j=0;j<i;++j)
    		for(rg int k=0;k+j<=t;++k){
    			pls(f[i][j][t-j],f[i-1][j][k]);
    			pls(f[i][j+1][k],1ll*f[i-1][j][k]*(t-j-k)%p);
    			if(k)pls(f[i][j+1][k-1],1ll*f[i-1][j][k]*k%p);
    		}
    	}
    }
    
    void print(){
    	for(rg int i=0;i<=n;++i)
    		pls(ans,f[n][i][0]);
    	printf("%d
    ",ans);
    }
    
    void init(){
    	read(n);
    	for(rg int i=1;i<=n;++i)
    		read(a[i]),read(b[i]);
    	sort(a+1,a+n+1,cmp);
    	sort(b+1,b+n+1,cmp);
    }
    
  • 相关阅读:
    java多线程学习-java.util.concurrent详解(四) Exchanger
    java多线程学习-java.util.concurrent详解(三) Semaphore
    java多线程学习-java.util.concurrent详解(二) CyclicBarrier
    java多线程学习-java.util.concurrent详解(一) CountDownLatch
    MongoDB 入门学习
    Protrator自动化测试(针对Angular 应用的自动化测试)
    Jasmine 编写 JavaScript 测试用例
    记录一下mysql忘记密码重置
    System.Data.DbType的字符串和数据库中字符串类型对应关系
    memcached和mongodb 在windows下安装
  • 原文地址:https://www.cnblogs.com/penth/p/9779072.html
Copyright © 2011-2022 走看看