其他分享
首页 > 其他分享> > [51Nod1773] A国的贸易 - 快速沃尔什变换

[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