日常训练 Idiot 的方程
2017-05-26 18:36
211 查看
题意简述:求以下不定方程非负整数解的组数 :∑ni=1Xi=m 0≤Xi≤li,i=1,2,3,…,n
数据范围:n≤20,m≤1018,li≤m
一开始毫无想法,因为上限限制只能背包,不能隔板,就是没想到容斥。
问题如果是有下界限制很好解决,所以容斥一发(感觉容斥好像有条件反向的作用),下界限制用隔板即可。
智障的我又忘记+P再取模了。
数据范围:n≤20,m≤1018,li≤m
一开始毫无想法,因为上限限制只能背包,不能隔板,就是没想到容斥。
问题如果是有下界限制很好解决,所以容斥一发(感觉容斥好像有条件反向的作用),下界限制用隔板即可。
智障的我又忘记+P再取模了。
#include<bits/stdc++.h> typedef long long ll; const int N = 25; const int P = 1234567891; int n; ll m,l ,inv ,ans; ll ksm(ll x, int k){ ll ans = 1; for (; k; k>>=1, x = x * x % P) if (k & 1) ans = ans * x % P; return ans; } ll C(ll n, ll k){ if (n < k) return 0; ll ans = 1; for (ll i=n; i>n-k; i--) ans = ans * (i % P) % P; for (int i=k; i>0; i--) ans = ans * inv[i] % P; return ans; } int main(){ scanf("%d%lld",&n,&m); for (int i=1; i<=n; i++) scanf("%lld",&l[i]); for (int i=1; i<=n; i++) inv[i] = ksm(i,P - 2); int all = 1 << n; for (int S=0; S<all; S++){ ll temp = m + n - 1, k = 1; for (int i=1; i<=n; i++) if (S & (1 << (i-1))) temp -= l[i] + 1, k *= -1; ans += C(temp,n-1) * k; } printf("%lld\n",(ans % P + P) % P); return 0; }
相关文章推荐
- 日常训练 Idiot 的集合
- [日常训练] tty的方程
- [日常训练] 联络网
- [日常训练] 最小生成树
- [日常训练] 我们爱序列
- [日常训练] 小Y包汤圆
- [日常训练] 分割田地
- NBA球员力量训练方法!感受职业球员日常训练!
- 日常训练 水箱
- 日常训练 20160601 B君的关系 羊毛 (Wolle) Burnside
- [日常训练] 藏宝路径
- 复试训练——动态规划——状态与转移方程
- 日常训练20161012 方块游戏
- 日常训练 20170531 探险
- 日常训练 20170602 B君的教育
- 日常训练 维护序列(包含区间除)
- Codeforces Round #424 (Div. 2)A-B-C 日常训练
- 日常训练 IQ测试 可持久化数组||链表
- 日常训练 20170605 EasyProblem
- 日常训练 20170622 数字游戏