经过n次翻牌以后,我们能得到在m张牌中最少有多少张1,和最多有几张1。然后翻牌数之和的奇偶性和1的张数的奇偶性一致。然后我们就对1的张数最少到最多求和。。就是答案了。。。中间要用到逆元。。因为算组合数不能打表(空间不够)。。也不能一层一层推(时间不够)。。。只能用扩展欧几里得来求了。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 100005 #define eps 1e-10 #define mod 1000000009 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; //typedef int LL; using namespace std; LL n, m; void extend_gcd(LL a, LL b, LL &d, LL &x, LL &y) { if(b == 0) { d = a, x = 1, y = 0; } else { extend_gcd(b, a%b, d, y, x), y -= x*(a/b); } } LL c[maxn]; int main(void) { LL a, b, aa, bb, i, x; LL g, y, ans; while(scanf("%I64d%I64d", &n, &m)!=EOF) { a = b = 0; for(i = 0; i < n; i++) { scanf("%I64d", &x); if(a >= x) aa = a-x; else if(b <= x) aa = x-b; else { if((a%2 && x%2) || (a%2 == 0 && x%2 == 0)) aa = 0; else aa = 1; } if(b+x <= m) bb = b+x; else if(a+x >= m) bb = m+m-a-x; else { if((((a+x)%2) && m%2) || (((a+x)%2 == 0) && m%2 == 0)) bb = m; else bb = m-1; } a = aa, b = bb; } c[0] = 1, ans = 0; for(i = 1; i <= m; i++) { extend_gcd(i, mod, g, x, y); x=(x%mod+mod)%mod; c[i] = c[i-1]*(m-i+1)%mod*x%mod; } for(i = a; i <= b; i+=2) { ans += c[i]; ans %=mod; } printf("%I64d\n", ans); } return 0; }