首页 > 代码库 > hdu - 4869 - Turn the pokers(组合数学 + 乘法逆元)
hdu - 4869 - Turn the pokers(组合数学 + 乘法逆元)
题意:m 张自牌,开始时全部正面朝下,翻转 n 次,每次翻转 xi 张牌,问最后的结果有多少种(0<n,m<=100000, 0<=Xi<=m)?
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4869
——>>假如最后有 a 张牌正面朝上,则它的结果有 C[m][a] 种(组合数),所以,只要求出最后可能有多少张牌正面朝上,再累加其组合数可行。。
1)求最后正面牌数的上下界;
2)以 2 为间隙进行枚举(因为连续的最小变动为2,头尾变)。
#include <cstdio> typedef long long LL; const int MOD = 1000000009; const int MAXN = 100000; int n, m; int L, R; LL f[MAXN + 10]; void Init() { L = R = 0; } void Read() { int x; for (int i = 0; i < n; ++i) { scanf("%d", &x); int bufR = R; if (R + x <= m) { R += x; } else { if (L + x > m) { R = m - (L + x - m); } else { if ((m - L - x) & 1) { R = m - 1; } else { R = m; } } } if (x <= L) { L -= x; } else { if (x > bufR) { L = x - bufR; } else { if ((x - L) & 1) { L = 1; } else { L = 0; } } } } } void Gcd(LL a, LL b, LL& d, LL& x, LL& y) { if (!b) { d = a; x = 1; y = 0; } else { Gcd(b, a % b, d, y, x); y -= a / b * x; } } LL Inv(int a, int n) { LL ret = 0, d, y; Gcd(a, n, d, ret, y); return d == 1 ? (ret + n) % n : -1; } void GetF() { f[0] = f[1] = 1; for (int i = 2; i <= MAXN; ++i) { f[i] = i * f[i - 1] % MOD; } } LL C(LL n, LL m) { return f[n] * Inv(f[m] * f[n - m] % MOD, MOD) % MOD; } void Solve() { LL ret = 0; for (int i = L; i <= R; i += 2) { ret = (ret + C(m, i)) % MOD; } printf("%I64d\n", ret); } int main() { GetF(); while (scanf("%d%d", &n, &m) == 2) { Init(); Read(); Solve(); } return 0; }
hdu - 4869 - Turn the pokers(组合数学 + 乘法逆元)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。