[51nod1773][A国的贸易][fwt]解题报告

来源:互联网 发布:js 防止sql注入 编辑:程序博客网 时间:2024/06/05 23:52

传送门 51nod1773

题意


给定序列A0...2n1,每次操作对于第i位,将第j位的数加到改位上,其中i=j ^ 2k,^为按位异或,kNk[0,n)
给定n,t,求t次操作后的序列A


分析


由题意有 Ai=Aj,其中i=ji=j^2k,kNk[0,n)
变一下,Ai=Aj×1, i=ji=j^2k,kNk[0,n)
于是变成了异或卷积的形式
构造数组B

Bi=1,0,if i=0 or i=2kelse
然后卷积异或就好了
记得快速幂
(记得写读入输出优化,我挂在这上面了
关于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;}
原创粉丝点击