1. 程式人生 > >51nod 1773 A國的貿易 (FWT)

51nod 1773 A國的貿易 (FWT)

基準時間限制:2 秒 空間限制:524288 KB 分值: 160 難度:6級演算法題

 收藏

 關注

A國是一個神奇的國家。這個國家有 2n 個城市,每個城市都有一個獨一無二的編號 ,編號範圍為0~2n-1。

A國的神奇體現在,他們有著神奇的貿易規則。

當兩個城市u,v的編號滿足calc(u,v)=1的時候,這兩個城市才可以進行貿易(即有一條邊相連)。
而calc(u,v)定義為u,v按位異或的結果的二進位制表示中數字1的個數。


ex:calc(1,2)=2         ——> 01 xor 10 = 11

       calc(100,101)=1 ——> 0110,0100 xor 0110,0101 = 1

       calc(233,233)=0 ——> 1110,1001 xor 1110,1001 = 0


每個城市開始時都有不同的貨物儲存量。

而貿易的規則是:
每過一天,可以交易的城市之間就會交易一次。

在每次交易中,當前城市u中的每個貨物都將使所有與當前城市u有貿易關係的城市貨物量 +1 。
請問 t 天后,每個城市會有多少貨物。
答案可能會很大,所以請對1e9+7取模。

Input

第一行兩個正整數 n , t,意義如題。
第二行 2^n 個非負整數,第 i 個數表示編號為 i-1 的城市的初始貨物儲存量。
n<=20  t<=10^9

Output

輸出一行 2^n 個非負整數。
第 i 個數表示過了 t 天后,編號為 i-1 的城市上的貨物數量對 1e9+7 取模的結果。

Input示例

樣例1:
3 2
1 2 3 4 5 6 7 8
樣例2:
1 1
0 1

Output示例

樣例1:
58 62 66 70 74 78 82 86
樣例2:
1 1

C++的執行時限為:2000 ms ,空間限制為:524288 KB 示例及語言說明請按這裡

 允許其他 AC 的使用者檢視此程式碼,分享程式碼才能檢視別人的程式碼並有機會獲得勳章

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn (1<<20)
#define mod 1000000007
const int rev=500000004;
char out[20];
int n,t,a[maxn],b[maxn],res[maxn];
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*10+ch-'0';ch=getchar();}
    return x*f;
}
void Put(int x)
{
    int num=0;
    while(x){
        out[++num]=x%10+'0';
        x/=10;
    }
    while(num)
        putchar(out[num--]);
    putchar(' ');
}
void fwt(int a[],int n){
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++){
                long long x=a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod;
                a[i+j+d]=(x-y+mod)%mod;
            }
}
void ufwt(int a[],int n){
    for(int d=1;d<n;d<<=1)
        for(int m=d<<1,i=0;i<n;i+=m)
            for(int j=0;j<d;j++){
                long long x=a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod;
                a[i+j+d]=(x-y+mod)%mod;
                a[i+j]=(ll)a[i+j]*rev%mod;
				a[i+j+d]=(ll)a[i+j+d]*rev%mod;
            }
}
void qpow(int k)
{
	for(int i=0;i<n;i++)
		res[i]=b[i];
	while(k)
	{
		if(k&1)
		{
			for(int i=0;i<n;i++)
				res[i]=1ll*res[i]*b[i]%mod;
		}
		for(int i=0;i<n;i++)
			b[i]=1ll*b[i]*b[i]%mod;
			k>>=1;
	}
	for(int i=0;i<n;i++)
		b[i]=res[i];
}
int main(void)
{
	n=read();t=read();
	t--;n=(1<<n);
	for(int i=0;i<n;i++)
		a[i]=read();
	for(int i=1;i<n;i<<=1)
		b[i]=1;b[0]=1;
	fwt(a,n);fwt(b,n);qpow(t);
	for(int i=0;i<n;i++)
		a[i]=1ll*a[i]*b[i]%mod;
	ufwt(a,n);
	for(int i=0;i<n;i++)
		Put(a[i]);
	printf("\n");
	return 0;
}