zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    C#中DateTime.Ticks属性及Unix时间戳转换
    SQL Server:统计数据库中每张表的大小
    SQL Server:统计数据库中每张表的大小
    SQL Server:统计数据库中每张表的大小
    SQL Server 2008 R2:快速清除日志文件的方法
    SQL Server 2008 R2:快速清除日志文件的方法
    SQL Server 2008 R2:快速清除日志文件的方法
    ACM_HDU 1231 最大连续子序列 (dp)_代码分析
    斑马难题Step by Step
    多种配置的分布式配置中心
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10136735.html
Copyright © 2011-2022 走看看