Aiiage Camp Day2 D domino

题意

  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
", ans);
47     }
48     
49     return 0;
50 }
原文地址:https://www.cnblogs.com/aseer/p/8442466.html