文章目录
题目链接:LightOJ 1124 Cricket Ranking
题目大意
有k个区间每个区间选出来一个数,使得k个数的和为n,问有多少种方案。
解题思路
这是一个多重集合的排列组合问题。
设
多
重
集
合
S
=
n
1
∗
a
1
,
n
2
∗
a
2
,
.
.
.
,
n
k
∗
a
k
,
n
=
n
1
+
n
2
+
.
.
.
+
n
k
设多重集合 S = { n_1 * a_1, n_2 * a_2, ..., n_k * a_k },n = n_1 + n_2 + ... + n_k
设多重集合S=n1∗a1,n2∗a2,...,nk∗ak,n=n1+n2+...+nk
即 集 合 S 中 含 有 n 1 个 元 素 a 1 , n 2 个 元 素 a 2 , . . . , n k 个 元 素 a k , n i 被 称 为 元 素 a i 的 重 数 , k 成 为 多 重 集 合 的 类 别 数 即集合 S 中含有n_1个元素a_1, n_2个元素a_2,...,n_k个元素a_k,n_i被称为元素a_i的重数,k成为多重集合的类别数 即集合S中含有n1个元素a1,n2个元素a2,...,nk个元素ak,ni被称为元素ai的重数,k成为多重集合的类别数
在 S 中 任 选 r 个 元 素 的 排 列 称 为 S 的 r 排 列 , 当 r = n 时 , 有 公 式 P ( n ; n 1 ∗ a 1 , n 2 ∗ a 2 , . . . , n k ∗ a k ) = n ! / ( n 1 ! ∗ n 2 ! ∗ . . . ∗ n k ! ) 在 S 中任选 r 个元素的排列称为S的r排列,当r = n时,有公式 P(n; n_1*a_1, n_2*a_2, ..., n_k*a_k) = n! / (n_1! * n_2! * ...* n_k!) 在S中任选r个元素的排列称为S的r排列,当r=n时,有公式P(n;n1∗a1,n2∗a2,...,nk∗ak)=n!/(n1!∗n2!∗...∗nk!)
在
S
中
任
选
r
个
元
素
的
组
合
称
为
S
的
r
组
合
,
当
r
<
=
任
意
n
i
时
,
有
公
式
C
(
n
;
n
1
∗
a
1
,
n
2
∗
a
2
,
.
.
.
,
n
k
∗
a
k
)
=
C
(
k
+
r
−
1
,
r
)
在 S 中任选 r 个元素的组合称为S的r组合,当r<=任意n_i时,有公式 C(n; n_1*a_1, n_2*a_2, ..., n_k*a_k) = C(k+r-1, r)
在S中任选r个元素的组合称为S的r组合,当r<=任意ni时,有公式C(n;n1∗a1,n2∗a2,...,nk∗ak)=C(k+r−1,r)
多重集合的排列和组合问题
大佬的本题题解
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=100000007;
ll ve[20];
ll poow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll C(ll n,ll m){
if(n<=m) return 1;
m=min(m,n-m);
ll res=1,ans=1;
for(ll i=0;i<m;i++){
res=res*(n-i)%mod;
ans=ans*(m-i)%mod;
}
return res*poow(ans,mod-2)%mod;
}
ll lucas(ll a,ll b){
if(a<b) return 0;
ll res=1;
while(b){
res*=C(a%mod,b%mod);
res%=mod;
a/=mod;b/=mod;
}
return res;
}
int main(){
int t,n,s;
cin>>t;
for(int ca=1;ca<=t;ca++){
cin>>n>>s;
ll x,y;
for(int i=0;i<n;i++){
cin>>x>>y;
s-=x;ve[i]=y-x;
}
cout<<"Case "<<ca<<": ";
ll ans=lucas(s+n-1,n-1);
ll N=1<<n;
for(int i=1;i<N;i++){
ll tem=s;int f=0;
for(int j=0;j<n;j++){
if((1<<j)&i){
f++;
tem-=ve[j]+1;
}
}
if(tem>=0){
if(f&1) ans-=lucas(tem+n-1,n-1);
else ans+=lucas(tem+n-1,n-1);
ans=(ans+mod)%mod;
}
}
cout<<ans<<"\n";
}
return 0;
}