无论怎么翻,每一步的1出现的可能个数的奇偶性是一样的,因为奇数 - 偶数 = 奇数,偶数 - 偶数 = 偶数,有一张牌被重叠了,那么就减去一个偶数2,所以怎么重叠都不会变(当前奇偶性与当前总翻牌数奇偶性一样),所以我们只要找到1的最大可能数,和最小可能数(当然最大和最小奇偶性一定相同),然后排列组合求和就行了,假如一共有10张牌,1出现的最大可能数是6 ,最小是2,那么ans = C(10 ,2) + C(10 ,4) + C(10 ,6).
最大和最小之间的同奇偶的数一定可以出现,就是搓1位,自己可以画画,这样又有一个蛋疼的问题,就是排列组合必然会涉及到除法,可是除法怎么处理这个 (a / b) % c因为他不等于 (a % c) / (b % c) ,乘法还可以,其实我们可以除法转化成乘法,使得(a / b) % c = a * pow(b ,c - 2) % c,这里的c是质数,下面证明一下
根据费马小定理有
a^(p - 1) % p = 1 % p
那么
(a^(p - 1) / a) % p = (1 / p) % p 则 a^(p - 2) = (1 / a) % p
除以a只要乘以1/a也就是乘以等号左侧,这样就把除法变成乘法。
注意成立的原因是在本题目里 a^(p-1)/p是一个大于等于p的数。
对于求1可能出现的次数min ,和max,就是分情况讨论,直接看代码自己模拟一下代码就懂了,这里就不解释了,全解释了读者看完也就没意思了。
#include<stdio.h> #define MOD 1000000009 __int64 X[110000]; __int64 C[110000]; __int64 quick_pow(__int64 a ,__int64 b) { __int64 c = 1; while(b) { if(b&1) c *= a; a *= a ,b /= 2; c %= MOD ,a %= MOD; } return c; } int main () { int n ,m ,i; while(~scanf("%d %d" ,&m ,&n)) { for(i = 1 ;i <= m ;i ++) scanf("%I64d" ,&X[i]); __int64 MIN = 0 ,MAX = 0; for(i = 1 ;i <= m ;i ++) { __int64 mi ,ma; if(X[i] <= MIN) mi = MIN - X[i]; else if(X[i] > MAX) mi = X[i] - MAX; else mi = (X[i]&1) != (MIN&1); if(X[i] + MAX <= n) ma = X[i] + MAX; else if(X[i] + MIN > n) ma = n * 2 - (MIN + X[i]); else ma = ((X[i] + MIN) & 1) == (n & 1) ? n : n - 1; MAX = ma ,MIN = mi; } __int64 sum = 0; C[0] = 1; if(MIN == 0) sum ++; for(i = 1 ;i <= MAX ;i ++) { if(n - i < i) C[i] = C[n-i]; else C[i] = C[i-1] * (n - i + 1) % MOD * quick_pow(i ,MOD - 2) % MOD; if(i >= MIN && (i&1) == (MIN&1)) sum = (sum + C[i]) % MOD; } printf("%I64d " ,sum); } return 0; }