# BZOJ 3992 [SDOI 2015] 序列统计 解题报告

  1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 typedef long long LL;
8 #define N 16384 + 5
9 #define Mod 1004535809
10 #define g 3
11
12 int n, p, x, m, len, w, d, root, inv_len, ans;
13 int T[N], Num[N], Pos[N];
14 int A[N], B[N], C[N], Rev[N], e[2][N];
15
16 inline int power(int u, int v, int p)
17 {
18     int res = 1;
19     for (; v; v >>= 1)
20     {
21         if (v & 1) res = (LL) res * u % p;
22         u = (LL) u * u % p;
23     }
24     return res;
25 }
26
27 inline void Init()
28 {
29     scanf("%d%d%d%d", &n, &p, &x, &m);
30     for (int i = 1; i <= m; i ++)
31         scanf("%d", T + i);
32     for (len = p << 1; len != (len & -len); len += (len & -len)) ;
33     for (int i = len; i > 1; i >>= 1) d ++;
34     inv_len = power(len, Mod - 2, Mod);
35     w = power(g, (Mod - 1) / len, Mod);
36 }
37
38 inline bool Judge(int x, int p)
39 {
40     for (int i = 2; i * i <= p; i ++)
41         if ((p - 1) % i == 0 && power(x, (p - 1) / i, p) == 1) return 0;
42     return 1;
43 }
44
45 inline int Find_Root(int p)
46 {
47     if (p == 2) return 1;
48     int res = 2;
49     for (; !Judge(res, p); res ++) ;
50     return res;
51 }
52
53 inline void Prepare()
54 {
55     root = Find_Root(p);
56     for (int i = 0; i < p - 1; i ++)
57     {
58         Num[i] = !i ? 1 : Num[i - 1] * root % p;
59         Pos[Num[i]] = i;
60     }
61 }
62
63 inline int Inc(int u, int v)
64 {
65     return u + v - (u + v >= Mod ? Mod : 0);
66 }
67
68 inline void FFT(int *Ar, int op)
69 {
70     for (int i = 0; i < len; i ++)
71         if (Rev[i] > i) swap(Ar[i], Ar[Rev[i]]);
72     for (int k = 1, s = 1; k < len; k <<= 1, s ++)
73         for (int i = 0; i < len; i ++)
74         {
75             if (i & k) continue ;
76             int t = (i & k - 1) << d - s;
77             int u = Inc(Ar[i], (LL) Ar[i + k] * e[op][t] % Mod);
78             int v = Inc(Ar[i], Mod - ((LL) Ar[i + k] * e[op][t] % Mod));
79             Ar[i] = u, Ar[i + k] = v;
80         }
81 }
82
83 inline void Convol(int *U, int *V)
84 {
85     for (int i = 0; i < len; i ++)
86         C[i] = V[i];
87     FFT(U, 0), FFT(C, 0);
88     for (int i = 0; i < len; i ++)
89         U[i] = (LL) U[i] * C[i] % Mod;
90     FFT(U, 1);
91     for (int i = 0; i < len; i ++)
92         U[i] = (LL) U[i] * inv_len % Mod;
93     for (int i = len - 1; i >= p - 1; i --)
94     {
95         U[i - p + 1] = Inc(U[i - p + 1], U[i]);
96         U[i] = 0;
97     }
98 }
99
100 inline void Solve()
101 {
102     A[0] = 1;
103     for (int i = 1; i <= m; i ++)
104     {
105         if (T[i] == 0) continue ;
106         B[Pos[T[i]]] ++;
107     }
108     for (int i = 0, inv_w = power(w, Mod - 2, Mod); i < len; i ++)
109     {
110         e[0][i] = !i ? 1 : (LL) e[0][i - 1] * w % Mod;
111         e[1][i] = !i ? 1 : (LL) e[1][i - 1] * inv_w % Mod;
112         for (int j = 0; j < d; j ++)
113             if ((i >> j) & 1) Rev[i] += 1 << (d - j - 1);
114     }
115     for (; n; n >>= 1)
116     {
117         if (n & 1) Convol(A, B);
118         Convol(B, B);
119     }
120     ans = A[Pos[x]];
121 }
122
123 int main()
124 {
125     #ifndef ONLINE_JUDGE
126         freopen("sequence.in", "r", stdin);
127         freopen("sequence.out", "w", stdout);
128     #endif
129
130     Init();
131     Prepare();
132     Solve();
133     printf("%d\n", ans);
134
135     #ifndef ONLINE_JUDGE
136         fclose(stdin);
137         fclose(stdout);
138     #endif
139     return 0;
140 }
3992_Gromah

posted @ 2015-04-16 09:11 Gromah 阅读(...) 评论(...) 编辑 收藏