# UOJ450 复读机

d = 2 / 3的时候，考虑生成函数。

f(x) = ∑[d | i] / (i!)

d = 3的时候用单位根反演，O(k2)枚举系数，同样算。因为我不想学单位根反演就没写...

 1 #include <bits/stdc++.h>
2
3 typedef long long LL;
4
5 const int N = 500010, MO = 19491001;
6
7 int n, k, d;
8
9 inline int qpow(int a, int b) {
10     int ans(1);
11     while(b) {
12         if(b & 1) {
13             ans = (LL)ans * a % MO;
14         }
15         a = (LL)a * a % MO;
16         b = b >> 1;
17     }
18     return ans;
19 }
20
21 namespace DP {
22     int f[110][1010], C[1010][1010];
23     inline void solve() {
24         f[0][0] = 1;
25         for(int i = 0; i <= 1000; i++) {
26             C[i][0] = C[i][i] = 1;
27             for(int j = 1; j < i; j++) {
28                 C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MO;
29             }
30         }
31         for(int i = 0; i < k; i++) {
32             for(int j = 0; j <= n; j++) {
33                 for(int p = 0; j + p <= n; p += d) {
34                     (f[i + 1][j + p] += (LL)f[i][j] * C[n - j][p] % MO) %= MO;
35                 }
36             }
37         }
38         printf("%d\n", f[k][n]);
39         return;
40     }
41 }
42
43 namespace D2 {
44
45     int fac[N], inv[N], invn[N];
46
47     inline int C(int n, int m) {
48         if(n < 0 || m < 0 || n < m) return 0;
49         return (LL)fac[n] * invn[m] % MO * invn[n - m] % MO;
50     }
51
52     inline void solve() {
53         fac[0] = inv[0] = invn[0] = 1;
54         fac[1] = inv[1] = invn[1] = 1;
55         for(int i = 2; i <= k; i++) {
56             fac[i] = (LL)fac[i - 1] * i % MO;
57             inv[i] = (LL)inv[MO % i] * (MO - MO / i) % MO;
58             invn[i] = (LL)invn[i - 1] * inv[i] % MO;
59         }
60
61         int ans = 0;
62         for(int i = 0; i <= k; i++) {
63             ans += (LL)C(k, i) * qpow(2 * i - k, n) % MO;
64             ans %= MO;
65         }
66         int temp = qpow((MO + 1) / 2, k);
67
68         printf("%lld\n", ((LL)temp * ans % MO + MO) % MO);
69         return;
70     }
71 }
72
73 int main() {
74
75     scanf("%d%d%d", &n, &k, &d);
76     if(d == 1) {
77         printf("%d\n", qpow(k, n));
78         return 0;
79     }
80     if(n <= 1000 && k <= 100) {
81         DP::solve();
82         return 0;
83     }
84     if(d == 2) {
85         D2::solve();
86         return 0;
87     }
88     return 0;
89 }
60分代码

posted @ 2019-06-30 22:03  huyufeifei  阅读(143)  评论(0编辑  收藏