10.05 T1 容斥+Lucas定理
Description
上条当麻又一次战斗到失去意识了
呱太医生冥土追魂又接到了病人当麻,为了让当麻立刻恢复健康,他需要对当麻的 n 个身体指标进行检查。对于每一个身体指标 xi,有上下界限制 di,ui 。当各个身体指标之和恰好为 m 时,当麻就能恢复意识,重新战斗。
为了让上条当麻尽快的醒过来,你需要告诉冥土追魂有多少组合法的身体指标。答案对 9999991 取模。
呱太医生冥土追魂又接到了病人当麻,为了让当麻立刻恢复健康,他需要对当麻的 n 个身体指标进行检查。对于每一个身体指标 xi,有上下界限制 di,ui 。当各个身体指标之和恰好为 m 时,当麻就能恢复意识,重新战斗。
为了让上条当麻尽快的醒过来,你需要告诉冥土追魂有多少组合法的身体指标。答案对 9999991 取模。
Input
第一行两个整数 n,m 。
接下来 n 行,每行两个整数表示 di 和 ui 。
接下来 n 行,每行两个整数表示 di 和 ui 。
Output
一个整数表示答案。
Sample Input
样例输入 1
1 5
4 7
样例输出 1
1
样例解释 1
我们可以发现当且仅当xi=5 时满足题意。
样例输入 2
3 10
1 5
1 5
1 5
样例输出 2
18
样例解释 2
我们用 (i,j,k) 表示x1=i,x2=j,x3=k,那么有以下方案:
(1,4,5);(1,5,4);
(2,3,5);(2,4,4);(2,5,3);
(3,2,5);(3,3,4);(3,4,3);(3,5,2);
(4,1,5);(4,2,4);(4,3,3);(4,4,2);(4,5,1);
(5,1,4);(5,2,3);(5,3,2);(5,4,1);
共 18 种方案。
Sample Output
Hint

Source
from liuxiao Trr
首先下界我们全部统一分配减去他们(对比之前的分特产有区别,因为那个题是要分小球的种类的,不能直接减掉)
然后m个小球分到n盒子里方案是
,然后我们要减去超出的(基本思路),然后我们就强制让k个必须超出,那么就这k个比上界多1,容斥一下就好了
,然后我们要减去超出的(基本思路),然后我们就强制让k个必须超出,那么就这k个比上界多1,容斥一下就好了我不会说我把 j 写成 i 查了半天错的
code:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const long long mod=9999991; 5 long long ksm(long long a,long long b){ 6 long long ans=1; 7 for(;b;b>>=1){ 8 if(b&1){ 9 ans*=a; 10 ans%=mod; 11 } 12 a*=a; 13 a%=mod; 14 } 15 return ans; 16 } 17 long long C(long long a,long long b){ 18 long long ans=1,up=1,down=1; 19 for(long long i=a-b+1;i<=a;i++)up=up*i%mod; 20 for(long long i=1;i<=b;i++)down=down*i%mod; 21 down=ksm(down,mod-2); 22 ans=(up*down)%mod; 23 return ans; 24 } 25 long long lucas(long long a,long long b){ 26 if(a<b)return 0; 27 if(!b)return 1; 28 return lucas(a/mod,b/mod)*C(a%mod,b%mod)%mod; 29 } 30 long long d[30],u[30]; 31 int main(){ 32 long long n,m; 33 cin>>n>>m; 34 for(long long i=1;i<=n;i++){ 35 cin>>d[i]>>u[i]; 36 m-=d[i]; 37 u[i]-=d[i]; 38 } 39 long long all=(1<<n)-1; 40 long long ans=lucas(m+n-1,n-1); 41 // cout<<ans; 42 for(long long i=1;i<=all;i++){ 43 long long temp=m,now=0; 44 for(long long j=1;j<=n;j++){ 45 if((i>>(j-1))&1){ 46 temp-=u[j]+1; 47 now++; 48 } 49 } 50 ///cout<<temp<<"\n"; 51 if(now&1){ 52 ans-=lucas(temp+n-1,n-1); 53 // cout<<"cut "<<lucas(temp+n-1,n-1)<<"\n"; 54 ans=(ans+mod)%mod; 55 } 56 else{ 57 ans+=lucas(temp+n-1,n-1); 58 // cout<<"add "<<lucas(temp+n-1,n-1)<<"\n"; 59 ans=(ans+mod)%mod; 60 } 61 } 62 cout<<ans%mod; 63 return 0; 64 }
over

浙公网安备 33010602011771号