码迷,mamicode.com
首页 > 其他好文 > 详细

多校 HDU 6397 Character Encoding (容斥)

时间:2018-08-16 22:24:36      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:type   容斥   数组   col   turn   rac   reg   条件   none   

  题意:在0~n-1个数里选m个数和为k,数字可以重复选;

    如果是在m个xi>0的情况下就相当于是将k个球分割成m块,那么很明显就是隔板法插空,不能为0的条件限制下一共k-1个位置可以选择插入隔板,那么也就是说一共有C(k-1, m-1)种组合(m-1是因为要m块只要m-1个隔板);

  回到这题,我们要求的并不是m个xi>0、而是xi>=0,但是隔板之间又不能为空,最少也是1,那就让m块每块都有一个球就好了,这样最少为1个的隔板间也就相当于是0个;但是此时的隔板插空处就又增加了,那么此时就变为将m+k个球分割成m块的问题,一共k+m-1个空,也就是组合数量为C(k+m-1, m-1);

  这样我们就知道了在xi无限制的情况下的组合数量,但是xi很明显是有限制的,对于xi有0<=xi<n;假设有m块里有1个xi>=n的情况下,要让问题保持在xi是取自[0, n-1]的范围内,那么就让那m块里其中一块变成已经放了n个球的情况,那么我们就相当于求在k-n+m-1个位置里插上m-1个隔板的方案数C(k-1*n+m-1, m-1);但是这个一块有m个位置可以选,也就是包括刚刚插空的方案还要加上选择时的方案即一共C(m, 1)*C(k-1*n+m-1, m-1);然后我们枚举当C(m, i)的i位为0~m时的所有情况, 令(-1)^i为容斥系数。也就是ans+=sum( (-1)^i * C(m, i)*C(k-i*n+m-1, m-1)  | 0<=i<=m )

下面给出代码加注释:

 

技术分享图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=2e5+7, INF=0x3f3f3f3f, mod=998244353;///在这里k+m在最大值是2e5所以说保存阶乘和阶乘逆的数组要开2e5
 5 void ex_gcd(ll a, ll b, ll &d, ll &x, ll &y){
 6     if (!b) {d = a, x = 1, y = 0;}
 7     else{
 8         ex_gcd(b, a % b, d, y, x);
 9         y -= x * (a / b);
10     }
11 }
12 ll Inv(ll a, ll p){
13     ll d, x, y;
14     ex_gcd(a, p, d, x, y);
15     return d == 1 ? (x % p + p) % p : -1;
16 }
17 ll inv[N]={1, 1};///保存i!的逆元
18 ll sum[N]={1, 1};///保存i!
19 ll getC(int n, int m){///得到C(n, m)
20     if(n<m||m<0){///如果不满足这些的情况是根本没有方案数的
21         return 0;
22     }
23     return ((sum[n]*inv[m])%mod)*inv[n-m]%mod;
24 }
25 int main( ){
26     register int i, n, m, k, T;
27     register ll l, ans;
28     for(l=2; l<N; ++l){
29         sum[l]=(sum[l-1]*l)%mod;
30         inv[l]=Inv(sum[l], mod);
31     }
32     scanf("%d", &T);
33     while(T--){
34         ans=0;
35         scanf("%d%d%d", &n, &m, &k);
36         for(i=0; i*n<=k; ++i){
37             if(i&1){
38                 ans=((ans-getC(m, i)*getC(k-i*n+m-1, m-1)%mod)%mod+mod)%mod;///
39             }else{
40                 ans=(ans+getC(m, i)*getC(k-i*n+m-1, m-1)%mod)%mod;///
41             }
42         }
43         printf("%lld\n", ans);
44     }
45 }
拙略的代码

 

多校 HDU 6397 Character Encoding (容斥)

标签:type   容斥   数组   col   turn   rac   reg   条件   none   

原文地址:https://www.cnblogs.com/DCD112358/p/9489931.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!