[51Nod1773] A国的贸易

Description

给定一个长度为 (2^n ( n le 20)) 的序列,编号从 (0) 开始,每次操作时,对于第 (i) 个数,他会加上所有下标为 (j) 的数(本轮操作之前的版本),其中 (i,j) 的二进制表示中有且仅有一位不同。求 (t le 10^9) 次操作后的序列在 (mod 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;
}

原文地址:https://www.cnblogs.com/mollnn/p/13581882.html