51nod 1773 A國的貿易 (FWT)
阿新 • • 發佈:2018-12-24
基準時間限制: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; }