10.05 T1 容斥+Lucas定理

Description

上条当麻又一次战斗到失去意识了
呱太医生冥土追魂又接到了病人当麻,为了让当麻立刻恢复健康,他需要对当麻的 n 个身体指标进行检查。对于每一个身体指标 xi,有上下界限制 di,ui 。当各个身体指标之和恰好为 m 时,当麻就能恢复意识,重新战斗。
为了让上条当麻尽快的醒过来,你需要告诉冥土追魂有多少组合法的身体指标。答案对 9999991 取模。

Input

第一行两个整数 n,m 。
接下来 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,容斥一下就好了
我不会说我把 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

posted @ 2018-10-05 16:41  saionjisekai  阅读(45)  评论(0)    收藏  举报