【51Nod1773】A国的贸易 解题报告

【51Nod1773】A国的贸易

Description

给出一个长度为 \(2^n\) 的序列,编号从\(0\)开始。每次操作后,如果 \(i\)\(j\) 的二进制表示只差一位则第 \(i\) 个数会加上操作前的第 \(j\) 个数。求 \(t\) 次操作后序列中的每个数是多少。

Input

第一行两个正整数 \(n\) ,\(t\),意义如题。
第二行 \(2^n\) 个非负整数,第 \(i\) 个数表示编号为 \(i-1\) 的城市的初始货物存储量。
\(n<=20 \ t<=10^9\)

Output

输出一行 \(2^n\) 个非负整数。
\(i\) 个数表示过了 \(t\) 天后,编号为 \(i-1\) 的城市上的货物数量对 \(1e9+7\) 取模的结果。


构造一个多项式\(F\)\(F_i=1\),当\(i\)\(2\)的正整数幂的时候。

然后答案就是\(D*F^t\),乘法是异或子集和,用\(FWT\)就可以了。

注意到不要写多项式快速幂,子集运算的长度是封闭的,所以化成类似点乘的形式后做快速幂即可,这样复杂度是\(O(n2^n)\)


Code:

#include <cstdio>
const int N=(1<<20)+10;
const int mod=1e9+7,inv=500000004;
namespace Fast{
    const int LEN=10000000;
    char inp[LEN],outp[LEN];
    int tmp[20];
    int inpos,outpos;
    void init(){
        fread(inp,1,LEN,stdin);
        inpos=0; outpos=0;
    }
    char GetChar(){return inp[inpos++];}
    int read(){
        int ret=0; char ch=GetChar();
        while (ch<'0'||ch>'9') ch=GetChar();
        while ('0'<=ch&&ch<='9') ret=ret*10+ch-'0',ch=GetChar();
        return ret;
    }
    void PutChar(char ch){outp[outpos++]=ch;}
    void print(int x){
        int pos=0;
        if (!x) tmp[++pos]=0;
        else
            while (x) tmp[++pos]=x%10,x/=10;
        for (int i=pos;i>=1;--i) PutChar(tmp[i]+'0');
    }
    void Print(){fwrite(outp,1,outpos,stdout);}
}
#define mul(a,b) (1ll*(a)*(b)%mod)
#define add(a,b) ((a+b)%mod)
int n,len,t,T[N],D[N];
void xorfwt(int *a,int typ)
{
    for(int le=1;le<len;le<<=1)
        for(int p=0;p<len;p+=le<<1)
            for(int i=p;i<p+le;i++)
            {
                int tx=a[i],ty=a[i+le];
                a[i]=add(tx,ty),a[i+le]=add(tx,mod-ty);
                if(!typ) a[i]=mul(a[i],inv),a[i+le]=mul(a[i+le],inv);
            }
}
int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
int main()
{
    Fast::init();
    n=Fast::read(),t=Fast::read(),len=1<<n;
    for(int i=0;i<len;i++) T[i]=Fast::read();
    D[0]=1;for(int i=0;i<n;i++) D[1<<i]=1;
    xorfwt(T,1),xorfwt(D,1);
    for(int i=0;i<len;i++) T[i]=mul(T[i],qp(D[i],t));
    xorfwt(T,0);
    for(int i=0;i<len;i++) Fast::print(T[i]),Fast::PutChar(' ');
    Fast::Print();
    return 0;
}

2018.12.18

posted @ 2018-12-18 14:01  露迭月  阅读(200)  评论(0编辑  收藏  举报