zoukankan      html  css  js  c++  java
  • 排列组合做题笔记

    牛客NOIP模拟第5场T3

    Description

    给定非负整数(a,b,c,d),求有多少对01串(S,T),满足以下条件:

    • S 由 a 个 0 , b 个 1 组成
    • T 由 c 个 0 , d 个 1 组成
    • T 可以由 S 删掉一些字符得到

    由于答案可能过大,你只需要输出答案对 1000000007 取模后的值

    • $a,b,c,d le 2 imes 10^3 ,cle a,dle b $

    Solution

    重点在于如何计算方案并做到不重不漏

    首先把求解方案数的过程看做构造T,然后把它填充成S

    大致可以这么计算:

    • 放一些01串在T的后面 【1】

    • 剩下的首先拼成T的雏形 【2】

    • 然后还有多余的0和1

      • 只允许把一些0插在T中“1”的前面 【3-1】

      • 只允许把一些1插在T中“0”的前面 【3-2】

    【1】过程可以(O((a-c) imes (b-d))) 枚举

    【2】过程就是 (C(c+d,d))

    【3-1】可以看成插板法,设有i个0放在最后,T串有 (d) 个1,那么就要把 (a-c-i) 个0安排在前面的 c个空隙中,方案数就为(C(d+a-c-i-1,d-1))

    同理设有j个1放在最后,【3-2】的方案数为 (C(c+b-d-j-1,c-1))

    Code

    #include<cstdio>
    #define FOR(i,x,y) for(int i=(x),i##_END=(y);i<=i##_END;++i)
    
    typedef long long LL;
    const int M=4005;
    const int P=1000000007;
    
    int C[M][M];
    int W(int i,int j){
    	if(i<0||j<0||i<j)return 0;
    	return C[i][j];
    }
    int S(int i,int j){return W(j+i-1,j-1);}
    
    int main(){
    	int a,b,c,d,ans=0;
    	scanf("%d%d%d%d",&a,&b,&c,&d);
    	FOR(i,0,M-1){
    		C[i][0]=C[i][i]=1;
    		FOR(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    	}
    	
    	if(!c&&!d)return printf("%d
    ",W(a+b,b)),0;
    	if(!d){
    		FOR(j,0,b-d)ans=(ans+S(b-j,a))%P; 
    		return printf("%d
    ",ans),0;
    	}
    	if(!c){
    		FOR(j,0,a-c)ans=(ans+S(a-j,b))%P;
    		return printf("%d
    ",ans),0;
    	}
    	FOR(i,0,a-c)FOR(j,0,b-d){
    		ans=(ans+(LL)W(i+j,j)*S(a-i-c,d)%P*S(b-j-d,c)%P)%P;
    	}
    	printf("%lld
    ",(LL)ans*W(c+d,d)%P);
    	
    	return 0;
    }
    
  • 相关阅读:
    5.2 HTML5表单与PHP交互
    5.1 HTML5表单的创建
    4.3 HTML5布局的使用
    MATLAB矩阵——2.5稀疏矩阵
    MATLAB矩阵——2.4矩阵的特征值与特征向量
    MATLAB矩阵——2.3矩阵求值
    MATLAB矩阵处理——2.2矩阵变换
    MATLAB矩阵处理——2.1特殊矩阵
    MATLAB基础知识——1.6基本运算
    MATLAB基础知识——1.5矩阵元素的引用
  • 原文地址:https://www.cnblogs.com/Zerokei/p/9794907.html
Copyright © 2011-2022 走看看