zoukankan      html  css  js  c++  java
  • 小奇的赏花(数学排列组合)

                                                       小奇的赏花

    题目描述

    小奇的花园里有n行m列棵桃花树,花色各不相同。小奇漫步在花园中,有时它觉得某一行/列的桃花很美,便会在这一整行/列的每棵树下捡一枚花瓣,到了傍晚,他发现自己选择了r行c列(同一行/列可能被选择不止一次)的花瓣。

    回家之后,小奇发现:有s种颜色的花瓣数为奇数,他想知道,有多少种选择方案能有这样的效果呢?(两种方案不同当且仅当某行/列被选择的次数不同)

    输入格式

    第一行包括5个整数,n,m,r,c,s。

    输出格式

    输出一个整数表示答案(mod 1000000007)。

    样例

    样例输入

    2 2 2 2 4
    

    样例输出

    4
    

    数据范围与提示

    对于 20% 的数据, n,m ≤ 4,r,c ≤ 4;

    对于 50% 的数据, n,m ≤ 500,r,c ≤ 2000;

    对于另外10% 的数据, n,m ≤ 100000,s = n * m;

    对于 100% 的数据, n,m ≤ 100000,r,c ≤ 100000,s ≤ 10^12。

    思路:这就是一道裸的数学排列组合题,设有x行被选择奇数次,有y列被选择奇数次,因为奇+偶=奇,奇+奇=偶,偶+偶=偶,而题中s为奇数,则可列出这样的等式:x*(m-y)+y*(n-x)=s,解得:y=(s-x*m)/(n-2*x),枚举x即可得出y,用每对x,y计算种类再加和,即为答案(分步加法)。那怎样计算每对x,y对应的种类数呢,当然用组合数求解。

    对于每对x,y而题目中限制只有r次,问题可转化成把r个苹果分到n个盘子中,保证有x个奇数盘子,先把x个苹果分别放到x个盘子中,方案数为Cxn,之后剩下(r-x)个苹果,把这些苹果分成(r-x)/2对放到n个盘子中允许为空,用隔板法解决。防止(r-x)/2对苹果填不满n个盘子,加上n个盘子,则有(r-x)/2对苹果和n个空分成n份放入n个不同的盘子(可以理解成有序)一共有(r-x)/2+n-1个空,插入n-1个隔板,方案数为Cn-1(r-x)/2+n-1    ,同理y也如此,则对每对x,y方案数为Cxn*Cn-1(r-x)/2+n-1*Cym*Cm-1(c-y)/2+m-1

    方案数用逆元求即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 const int mod=1000000007,maxn=200000+10;
     6 ll r,c,n,m;
     7 ll f[maxn],fac[maxn],ine[maxn];
     8 ll s;
     9 void Init(){
    10     fac[0]=1;
    11     for(int i=1;i<=200000;i++) fac[i]=fac[i-1]*i%mod;//求阶乘
    12     ine[1]=1;
    13     for(int i=2;i<=200000;i++){
    14         ll a=mod/i;
    15         ll b=mod%i;
    16         ine[i]=(-a*ine[b]%mod+mod)%mod;//线性求逆元
    17     }
    18     f[0]=1;
    19     for(int i=1;i<=200000;i++) f[i]=f[i-1]*ine[i]%mod;//逆元的阶乘
    20 }
    21 ll cmb(ll x,ll y){
    22     ll cnt=1;
    23     cnt=cnt*f[x]%mod;
    24     cnt=cnt*f[y-x]%mod;
    25     cnt=fac[y]*cnt%mod;
    26     return cnt;
    27 }//组合数
    28 ll cal(int x,int y){
    29     if((r-x)%2||(c-y)%2) return 0;//当(r-x)/2或(c-y)/2不为整数时,不成立,因为若(r-x)为奇数,它分出若干份偶数个苹果,最后肯定剩下一个苹果,这个苹果若放在
    30     ll cnt=1;                     //那x个盘子中则有一个盘子不为奇数,若放在其余盘子中,则多一个盘子为奇数
    31     cnt=cnt*cmb(x,n)%mod;
    32     cnt=cnt*cmb(n-1,(r-x)/2+n-1)%mod;
    33     cnt=cnt*cmb(y,m)%mod;
    34     cnt=cnt*cmb(m-1,(c-y)/2+m-1)%mod;
    35     return cnt;
    36 }//每对x,y对应的方案数
    37 int main(){
    38     scanf("%lld%lld%lld%lld%lld",&n,&m,&r,&c,&s);
    39     Init();
    40     ll ans=0;
    41     for(ll i=0;i<=min(n,r);i++){
    42         if(n==2*i){
    43             if(s==i*m){
    44                 for(ll j=0;j<=min(m,c);j++) ans=(ans+cal(i,j))%mod;
    45             }//注意枚举x时当(n==2*i&&s==i*m)此时j可取范围以内的任何值                    
    46         }
    47         else{
    48             if((s-i*m)%(n-2*i)==0){
    49                 ll y=(s-i*m)/(n-2*i);
    50                 if(y<=min(m,c)&&y>=0) ans=(ans+cal(i,y))%mod;
    51             }
    52         }
    53     }
    54     printf("%lld
    ",ans);
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    MySQL--CREATE INDEX在各版本的优化
    MySQL--各版本DDL 操作总结
    MySQL--事务隔离级别RR和RC的异同
    MySQL--运维内参中的binlog_summary脚本
    认知:人性
    诉衷情
    初中生读物
    DTO和Entity转换
    layui开发常用插件列表
    mongodb配置
  • 原文地址:https://www.cnblogs.com/HZOIDJ123/p/13392005.html
Copyright © 2011-2022 走看看