[51Nod1773] A国的贸易 - 快速沃尔什变换
作者:互联网
Description
给定一个长度为 \(2^n ( n \le 20)\) 的序列,编号从 \(0\) 开始,每次操作时,对于第 \(i\) 个数,他会加上所有下标为 \(j\) 的数(本轮操作之前的版本),其中 \(i,j\) 的二进制表示中有且仅有一位不同。求 \(t \le 10^9\) 次操作后的序列在 \(\bmod 10^9 + 7\) 下的结果。
Solution
构造数组 \(b[]\),其中 \(1,2,4,8,...\) 位置为 \(1\),其余均为 \(0\),则显然每次操作后的序列 \(a'[]\) 就是原序列 \(a[]\) 和 \(b[]\) 的异或卷积,于是目标序列 \(c[]=a[]*b[]^t\)
用 FWT 将异或卷积转化为算数乘法,用快速幂解决即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1 << 21 | 1;
const int mod = 1e9+7;
int T;
int qpow(int p,int q)
{
return (q&1 ? p : 1) * (q ? qpow(p*p%mod,q/2) : 1) % mod;
}
int inv(int p)
{
return qpow(p, mod-2);
}
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;
}
void write(int x)
{
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
void rd(int &x)
{
x=read();
}
void md(int &a)
{
a%=mod;
a+=mod;
a%=mod;
}
//////////////////////////
namespace fwt
{
int n, m;
int a[N], b[N];
void load(int m, int *A, int *B)
{
n = 1 << m;
for (int i = 0; i < n; i++) a[i] = A[i], b[i] = B[i];
}
void get()
{
for(int i=0;i<n;i++) b[i]=qpow(b[i],T);
for (int i = 0; i < n; i++) a[i] *= b[i], md(a[i]);
}
void OR(int *f, int x = 1)
{
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j+k] += f[i+j] * x, md(f[i+j+k]);
}
void AND(int *f, int x = 1)
{
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k] * x, md(f[i+j]);
}
void XOR(int *f, int x = 1)
{
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k],
f[i+j+k] = f[i+j] - f[i+j+k] - f[i+j+k],
md(f[i+j]), md(f[i+j+k]),
f[i+j] *= x, f[i+j+k] *= x,
md(f[i+j]), md(f[i+j+k]);
}
void solve_and(int m,int *A,int *B,int *c)
{
load(m,A,B), AND(a), AND(b), get(), AND(a, mod - 1);
memcpy(c,a,(1<<m)*sizeof(int));
}
void solve_or(int m,int *A,int *B,int *c)
{
load(m,A,B), OR(a), OR(b), get(), OR(a, mod - 1);
memcpy(c,a,(1<<m)*sizeof(int));
}
void solve_xor(int m,int *A,int *B,int *c)
{
load(m,A,B), XOR(a), XOR(b), get(), XOR(a, inv(2));
memcpy(c,a,(1<<m)*sizeof(int));
}
} // namespace fwt
int A[N], B[N], C[N];
signed main()
{
int n, m;
rd(m), n = 1 << m;
rd(T);
for (int i = 0; i < n; i++) rd(A[i]);
for (int i=0;i<m;i++) B[1<<i]=1;
B[0]=1;
fwt::solve_xor(m,A,B,C);
for(int i=0; i<n; i++) write(C[i]), putchar(' ');
return 0;
}
标签:10,51Nod1773,ch,变换,void,int,沃尔什,序列,mod 来源: https://www.cnblogs.com/mollnn/p/13581882.html