安全系统(杨辉三角求组合数)

题目传送门

题目大意
给你n个盒子,每个盒子里可以放0或者1,可以只放一个,可以都放,可以都不放,现在有a个1,b个0,每个1或每个0各不相同,问你有多少种方案去放。

数据范围
a,b≤50,n+a\le 50n+a≤50,n+b\le 50n+b≤50

思路
注意每个1(或者0)都不同,这卡了我很久。 ,这题很容易想到组合数学的解法。因为互不影响,我们可以先放1,再放0。对于放1,我们可以在a个1中选取i个1,然后再n个位置里选i个位置放1,就相当于Cni *Cai,对0同理。最后对放1的方案数和放0的方案数相乘就行了。

但是如果我们按照公式,用阶乘去算组合数,会爆精度,所以我们要另辟蹊径。
之前写过一篇杨辉三角求组合数的问题,这里可以用上。数据开ull

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int eps=1e-6;
typedef long long ll;
typedef unsigned long long ull;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
ull c[N][N];
void zuhe()
{
    c[0][0]=1;
    for(int i=1;i<=55;i++)
    {
        for(int j=0;j<=i;j++)
        {
            c[i][j]=c[i-1][j];
            if(j!=0)
                c[i][j]+=c[i-1][j-1];
        }
    }
}
signed main()
{
    IOS;
    int n,a,b;
    cin>>n>>a>>b;
    zuhe();
    ull res=0;
    ull tt=0;
    for(int i=0;i<=min(a,n);i++)
    {
        tt+=c[n][i]*c[a][i];
    }
    res=tt;tt=0;
    for(int i=0;i<=min(b,n);i++)
    {
        tt+=c[n][i]*c[b][i];
    }
    res*=tt;
    cout<<res<<endl;
}

发布了93 篇原创文章 · 获赞 9 · 访问量 4203

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/104851838
今日推荐