8.21 T2 矩阵补全(FWT)

本文搬运自本人高中时期CSDN博客,若图片加载不出来,可到原文查看:https://blog.csdn.net/zhangtingxiqwq/article/details/141403062

http://cplusoj.com/d/senior/p/NODSX2302B

考虑 bi{1}b_i\in\{1\} 怎么做,这是个裸的FWT,FWT后弄个快速幂就行

如果 bi{0,1}b_i\in\{0,1\} ,在0的位我们就要保持原样不能动

bi{0,1,2,3}b_i\in\{0,1,2,3\} ,同理,在对应的位置上我们实行对应的操作。也就是把FWT的每一层弄成 bb 指定的操作即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#define debag(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#define debag(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
#define mo (int)(1e9 + 7)
#define N 2000010
int pw(int a, int b) {
int ans = 1;
while(b) {
if(b & 1) ans *= a;
a *= a; b >>= 1;
ans %= mo; a %= mo;
}
return ans;
}
const int inv2 = pw(2, mo-2);
int n, m, i, j, k, T;
int A[N], a[N], b[N], o, P, l;
char str[N];

void cp() {
for(i = 0; i < n; ++i) a[i] = A[i];
}

void FWT(int *f, int x) {
for(k = 1, o = 2, l = 0; o <= n; o <<= 1, k <<= 1, ++l) {
if(b[l] == 1) {
for(i = 0; i < n; i += o)
for(j = 0; j < k; ++j)
f[i + j + k] = (f[i + j + k] + f[i + j] * x) % mo;
}
if(b[l] == 2) {
for(i = 0; i < n; i += o)
for(j = 0; j < k; ++j)
f[i + j] = (f[i + j] + f[i + j + k] * x) % mo;
}
if(b[l] == 3) {
for(i = 0; i < n; i += o)
for(j = 0; j < k; ++j) {
int y = (x == 1 ? 1 : inv2);
f[i + j] += f[i + j+ k];
f[i + j + k] = f[i + j] - 2 * f[i + j + k];
f[i + j] = f[i + j] * y % mo;
f[i + j + k] = f[i + j + k] * y % mo;
}
}
}
debug("l : %lld\n", l);
assert(l == m);
}

void mul() {
for(i = 0; i < n; ++i) a[i] = pw(a[i], P);
}

signed main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }
P = read(); m = read(); n = (1 << m);
scanf("%s", str);
for(i = 0; i < n; ++i) A[i] = str[i] - '0';
for(i = 0; i < m; ++i) b[i] = read();
for(i = 0; i < n; ++i) debug("%lld ", A[i]); debug("\n");
cp(); FWT(a, 1);
for(i = 0; i < n; ++i) debug("%lld ", a[i]); debug("\n");
mul(); FWT(a, -1);
int q = read();
while(q--) {
int x = read();
printf("%lld\n", (a[x] % mo + mo) % mo);
}
return 0;
}