zoukankan      html  css  js  c++  java
  • 51NOD 1773:A国的贸易——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1773

    参考1:FWT讲解 https://www.cnblogs.com/RabbitHu/p/9182047.html

    参考2:题解 https://www.cnblogs.com/ivorysi/p/9178577.html

    (令$oplus$表示异或)

    设$dp[i][j]$表示第$i$天$j$编号城市货物数。

    因为只有$i oplus j$的答案有一个1才能转移,所以$ioplus j=2^k$

    根据异或的性质变成$ioplus 2^k=j$。

    想办法利用它把转移方程写成卷积的形式。

    设$b[2^i]=1$,其余都是$0$,于是就有:

    $dp[i][j]=dp[i-1][j]+sum_{aoplus k=j}dp[i-1][a]*b[k]$

    你会发现把$dp$递归展开之后实际上就是一个卷积套卷积……套$t$次的过程,$FWT$运算加快速幂即可。

    注意读入输出优化。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1<<20;
    const int p=1e9+7;
    const int inv=500000004;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    void write(int x){
        if(x>9)write(x/10);
        putchar('0'+x%10);
    }
    inline int add(int x,int y){
        x+=y;if(x>=p)x-=p;return x;
    }
    inline int sub(int x,int y){
        x-=y;if(x<0)x+=p;return x;
    }
    void FWT(int a[],int n,int on){
        for(int i=1;i<n;i<<=1){
        for(int j=0;j<n;j+=(i<<1)){
            for(int k=0;k<i;k++){
            int u=a[j+k],t=a[j+k+i];
            a[j+k]=add(u,t);
            a[j+k+i]=sub(u,t);
            if(on==-1){
                a[j+k]=(ll)a[j+k]*inv%p;
                a[j+k+i]=(ll)a[j+k+i]*inv%p;
            }
            }
        }
        }
    }
    int qpow(int k,int n){
        int res=1;
        while(n){
        if(n&1)res=(ll)res*k%p;
        k=(ll)k*k%p;n>>=1;
        }
        return res;
    }
    int n,t,m,a[N],b[N];
    int main(){
        n=read(),t=read(),m=1<<n;
        for(int i=0;i<m;i++)a[i]=read();
        for(int i=0;i<m;i++){
        if(i-(i&-i)==0)b[i]=1;
        }
        FWT(a,m,1);FWT(b,m,1);
        for(int i=0;i<m;i++)a[i]=(ll)a[i]*qpow(b[i],t)%p;
        FWT(a,m,-1);
        for(int i=0;i<m;i++){
        write(a[i]);putchar(' ');
        }
        puts("");
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    HttpModule和HttpHandler
    SharePoint
    两种遍历Hashtable方法(小技巧)
    在线游戏开发人员的行话
    AS3 条件编译
    Flash开发MMORPG的时候一些技术障碍
    Java实现几种常见排序方法
    画贝塞尔曲线
    一一解答
    如何留住核心人才?
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9190262.html
Copyright © 2011-2022 走看看