$\huge \color{orange}{成魔之路->}$ $\huge \color{purple}{算法提高课题解}$
思路:
$假设第\ i\ 个盒子选\ x_i\ 枝花且每个盒子有无数枝花,那么\ x_1+x_2+…+x_n=m\ (x_i\ge 0)$
$令\ x_i=y_i-1,则\ y_1+y_2+…+y_n=m+n\ (y_i>0),则方案数为\ C_{m+n-1}^{n-1}$
$假设\ S_i\ 表示第\ i\ 个盒子选择的花超出限制\ A_i\ 的方案数$
$\begin{aligned}合法方案 & = 总方案-不合法方案 \\\\ & =C_{m+n-1}^{n-1}-(S_1\cup S_2\cup… \cup S_n)\\\\ & = C_{m+n-1}^{n-1}-\sum\limits_{i}C_{m+n-1-(A_i+1)}^{n-1}+\sum\limits_{i<j}C_{m+n-1-(A_i+1)-(A_j+1)}^{n-1}-…\end{aligned}$
本题思路: $用二进制表示所有方案,1表示该位不满足条件,0表示该位满足条件$
完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 25, mod = 1e9 + 7;
LL n,m;
LL A[N];
int down=1;
int qmi(int a,int b,int p)
{
int res=1;
while(b)
{
if(b&1) res=(LL)res*a%p;
a=(LL)a*a%p;
b>>=1;
}
return res;
}
int C(LL a,LL b)
{
if(a<b) return 0;
int up=1;
for(LL i=a;i>a-b;i--) up=i%mod*up%mod;
return (LL)up*down%mod;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>A[i];
for(int i=1;i<n;i++) down=(LL)down*i%mod;
down=qmi(down,mod-2,mod); //逆元
int res=0;
for(int i=0;i<1<<n;i++) //二进制枚举所有方案
{
LL a=m+n-1,b=n-1;
int sign=1;
for(int j=0;j<n;j++) //枚举所有位
if(i>>j&1) // 1 表示该位不满足条件
{
sign*=-1;
a-=A[j]+1;
}
res=(res+C(a,b)*sign)%mod;
}
cout<<(res+mod)%mod<<endl;
return 0;
}
latex editing is not standardized anymore, it will affect the rendering, only the formula part is needed
$假设第\ i\ 个盒子选\ x_i\ 枝花且每个盒子有无数枝花,那么$
$假设第\ i\ 个盒子选\ x_i\ 枝花且每个盒子有无数枝花,那么$
这是您的 $\LaTeX$ 代码,正确的 LaTeX 使用方法应该是只在数学公式下使用 LaTeX。可以这样改一下:
假设第 $i$ 个盒子选 $x_i$ 枝花且每个盒子有无数枝花,那么
假设第 $i$ 个盒子选 $x_i$ 枝花且每个盒子有无数枝花,那么
OKOK,学到了!