题目传送门
题目大意
给你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;
}