题意
2*∞上放x+y个2*1的骨牌,其中x个骨牌必须横置。求%MOD的方案数。
T<=1e3
x+y<=2e3
1e8<=MOD<=1e9+7
题解
Sigma{C(x + y - i, i) * C(i * 2, x), (x + 1) / 2 <= i <= (x + y) / 2}
假设有i*2个横置骨牌(横置骨牌必然成对出现),则排列方案数有C(x + y - i, i),染色方案有C(i * 2, x)。求和即可。
现场用log求逆元的方法过了,但无法在NXUOJ上通过。换成线性预处理就过了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 LL jc[2010], inv[2010]; 7 8 void ycl(int MOD) 9 { 10 jc[0] = 1; 11 for (int i = 1; i <= 2000; ++i) 12 { 13 jc[i] = jc[i - 1] * i; 14 if (jc[i] >= MOD) 15 jc[i] %= MOD; 16 } 17 inv[1] = 1; 18 for (int i = 2; i <= 2000; ++i) 19 inv[i] = (LL)(MOD - MOD / i) * inv[MOD % i] % MOD; 20 inv[0] = 1; 21 for (int i = 1; i <= 2000; ++i) 22 inv[i] = inv[i - 1] * inv[i] % MOD; 23 } 24 25 LL C(LL n, LL m, int MOD) 26 { 27 return (jc[n] * inv[n - m] % MOD * inv[m] % MOD) % MOD; 28 } 29 30 int main() 31 { 32 int T; 33 scanf("%d", &T); 34 while (T--) 35 { 36 int x, y, mod; 37 scanf("%d%d%d", &x, &y, &mod); 38 ycl(mod); 39 LL ans(0); 40 for (int i = (x + 1) / 2; i <= (x + y) / 2; ++i) 41 { 42 ans += (C(x + y - i, i, mod) * C(i * 2, x, mod)) % mod; 43 if (ans >= mod) 44 ans %= mod; 45 } 46 printf("%d\n", ans); 47 } 48 49 return 0; 50 }