[容斥+lucas] LightOJ 1124 - Cricket Ranking
来源:互联网 发布:程序员一般用什么键盘 编辑:程序博客网 时间:2024/05/16 00:47
LightOJ 1124 - Cricket Ranking
题意:有k个区间[l, r],从每个区间里取一个整数,问k个数和为n的方法数。
题解:显然的,题目可以转化成从k个区间[0, r[i]-l[i]] (1<=i<=k)里取k个数和为s=n-sum(l)的方法数,并令v[i] = r[i]-l[i]。
可以理解成x1+x2+x3+...xn = s的非负整数解的个数,其中xi∈[0, v[i]]。
A*表示我们需要求的多重集合,A*={v[1]*a1, v[2]*a2, ..., v[n]*an},认为a1=a2=a3=..an=1即可,假如选了ri(0<=r<=v[i])个ai,那么xi的值就是ri,并且有r1+r2+r3+...+rn = s,这就是多重集合的s组合和这个方程之间的关系。
显然,答案就是A*的s组合的个数。
先不考虑上限,即每个数可能超过v[i],也可能没有超过,这个新集合可以表示为A={∞*a1, ∞*a2, ..., ∞*an}。
那么新集合A的s组合个数的计算方法,是个经典的n种元素无限重数的多重集合的s组合问题,这个结果为|As|=C(s+n-1, n-1),As表示A的所有s组合。
然后应用容斥原理。
我们对于i=1,2,3...,用Pi表示第i个数超过v[i]的性质,对于i=1,2,3....用Ai表示As中具有Pi性质的组合的集合,也就是Ai表示第i个盒子不合法的情况的集合。
如果用!Ai表示Ai的补集,那么要求的答案ans=|!A1∩!A2∩!A3∩....∩!An|。
根据集合知识,ans = |A| - |(A1∪A2∪A3∪...∪An)|
由于其他的类似,我们来讨论|A1|如何计算。
显然A1是A中r1>=v[1]+1的那些组合组成的。
如果从A1中取出任意一个元素,并减去v[1]+1个x1,那么我们就得到A的s-v[1]-1组合的一个元素。
如果从A的s-v[1]-1组合中取出任意一个元素,并加上v[1]+1个x1,那么就得到A1的一个元素。
容易证明|A1|=|A的s-v[1]-1组合|,这个组合的计算前面说过了,等于C( (s-v[1]-1)+n-1, n-1)。
后面多个集合的并的计算方法就是容斥公式和lucas组合数+逆元快速幂了。
用二进制枚举任意非法状态。
#include<cstdio>using namespace std;typedef long long ll;const int mod = 100000007;ll n, s;ll v[15];ll qpow(ll a, ll k){ ll res = 1; while(k){ if(k&1) { res *= a; if(res >= mod) res %= mod; } a *= a; if(a >= mod) a %= mod; k >>= 1; } return res;}ll C(ll a, ll b){ if(a < b) return 0; if(b > a-b) b = a-b; ll up = 1, down = 1; for(ll i = 0; i < b; ++i){ up *= (a-i); if(up >= mod) up %= mod; down *= (i+1); if(down >= mod) down %= mod; } return up*qpow(down, mod-2)%mod;}ll lucas(ll a, ll b){ ll res = 1; while(b){ res *= C(a%mod, b%mod); if(res >= mod) res %= mod; a/= mod, b /= mod; } return res;}ll solve(){ ll ans = lucas(s+n-1, n-1); // 全集 ll mx = 1<<n; int f[2] = {1, -1}; for(int i = 1; i < mx; ++i){ int flag = 0; ll tmp = s; for(int j = 0; j < n; ++j){ if(i&(1<<j)){ tmp -= v[j]+1; flag += 1; } } if(tmp < 0) continue; ans += f[flag&1]*lucas(tmp+n-1,n-1); // 容斥公式 if(ans < 0) ans += mod; else if(ans >= mod) ans %= mod; } return ans;}int main(){ int T, ca = 1; scanf("%d", &T); while(T--){ ll sum = 0; scanf("%lld%lld", &n, &s); for(int i = 0; i < n; ++i){ ll l, r; scanf("%lld%lld", &l, &r); r -= l, s -= l, v[i] = r; } printf("Case %d: %lld\n", ca++, solve()); }}
- [容斥+lucas] LightOJ 1124 - Cricket Ranking
- codeforces - E. Devu and Flowers & LightOJ 1124 Cricket Ranking(容斥定理+lucas定理)
- uva 10458 - Cricket Ranking(容斥+高精度)
- UVA 10458 - Cricket Ranking(容斥原理)
- UVA 10458 Cricket Ranking (容斥)
- UVa 10458 - Cricket Ranking (容斥)
- hdu5794 lucas定理+容斥
- LightOJ 1144 容斥
- lightoj - 1299 - Fantasy Cricket - dp
- Lightoj 1095 容斥原理
- HDU_5794_ASimpleChess(Lucas定理&&(容斥||dp))
- HDU 5794 容斥原理+Lucas
- hdu3929 容斥+扩展Lucas定理
- 【HDU5794】 A Simple Chess(Lucas+容斥)
- HDU - 5794 dp + 容斥思想 + Lucas
- codeforces451E容斥原理加lucas
- LightOj 1067(Lucas)
- [容斥] LightOJ 1117 - Helping Cicada
- UVa 11464 偶数矩阵 枚举
- 作用域链
- int转换成二进制字符串
- 如何搭建Jenkins持续集成测试环境
- Kotlin 流程控制
- [容斥+lucas] LightOJ 1124 - Cricket Ranking
- 读取、创建Json格式数据
- 文件的上传与下载
- hdu1465不容易系列之一
- Kaggle Titanic: Machine Learning from Disaster 一种思路
- Spring:关于ApplicationContext
- ForkJoin框架
- ffplay相关函数
- Problem N