传送门 51nod1773
题意
给定序列
A0...2n−1
,每次操作对于第
i
位,将第
给定
n,t
,求
t
次操作后的序列
分析
由题意有
Ai=∑Aj
,其中
i=j
或
i=j
^
2k
,
k∈N
且
k∈[0,n)
变一下,
Ai=∑Aj×1
,
i=j
或
i=j
^
2k
,
k∈N
且
k∈[0,n)
于是变成了异或卷积的形式
构造数组
B
然后卷积异或就好了
记得快速幂
(记得写读入输出优化,我挂在这上面了
关于fwt,推荐riteme的blog riteme orz
代码
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = (1 << 20) | 1;
const int mod = 1e9 + 7;
const int inv = 5e8 + 4;
int A[N], B[N];
int n, t;
int getint()
{
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
void print(int x)
{
int num = 0; char c[15];
while (x) c[++ num] = (x % 10) + 48, x /= 10;
while (num) putchar(c[num--]);
putchar(' ');
}
int inc(int a, int b)
{
return a + b - (a + b >= mod ? mod : 0);
}
void fwt(int *a, int len)
{
int b[len];
for (int dis = 2; dis <= len; dis <<= 1)
{
for (int i = 0; i < len; i += dis)
{
int mid = dis >> 1;
for (int j = 0; j < mid; j ++)
{
b[i + j] = inc(a[i + j], a[i + mid + j]);
b[i + j + mid] = inc(a[i + j], mod - a[i + j + mid]);
}
}
for (int i = 0; i < len; i ++) a[i] = b[i];
}
}
void ifwt(int *a, int len)
{
int b[len];
for (int dis = 2; dis <= len; dis <<= 1)
{
for (int i = 0; i < len; i += dis)
{
int mid = dis >> 1;
for (int j = 0; j < mid; j ++)
{
b[i + j] = (ll) inc(a[i + j], a[i + mid + j]) * inv % mod;
b[i + j + mid] = (ll) inc(a[i + j], mod - a[i + j + mid]) * inv % mod;
}
}
for (int i = 0; i < len; i ++) a[i] = b[i];
}
}
void pow(int b)
{
int ret[n];
for (int i = 0; i < n; i ++) ret[i] = 1;
while (b)
{
if (b & 1)
for (int i = 0; i < n; i ++)
ret[i] = (ll) ret[i] * B[i] % mod;
b >>= 1;
for (int i = 0; i < n; i ++)
B[i] = (ll) B[i] * B[i] % mod;
}
for (int i = 0; i < n; i ++) B[i] = ret[i];
}
int main()
{
n = getint(); t = getint(); n = (1 << n);
for (int i = 0; i < n; i ++) A[i] = getint();
for (int i = 1; i < n; i <<= 1) B[i] = 1;
B[0] = 1;
fwt(A, n); fwt(B, n);
pow(t);
for (int i = 0; i < n; i ++) A[i] = (ll) A[i] * B[i] % mod;
ifwt(A, n);
for (int i = 0; i < n; i ++) print(A[i]);
return 0;
}