1. 程式人生 > >BZOJ3645: Maze(FFT多項式快速冪)

BZOJ3645: Maze(FFT多項式快速冪)

告訴 這樣的 typedef 小孩 tput 刪除 註意 一個 out

Description

眾維拉先後在中土大陸上創造了精靈、人類以及矮人,其中矮人是生性喜好常年居住在地下的洞穴的存在,他們挖掘礦物甚至寶石,甚至用他們的勤勞勇敢智慧在地底下創造出了輝煌宏大的宮殿,錯綜復雜的迷宮——嗯,沒錯,現在KPM這個毛小孩要扯上關系的就是迷宮啦~
描述
KPM在矮人的王國發現了一個迷宮,現在這個迷宮是這樣的:迷宮的主體由排列成一個整齊的n行m列的矩陣的房間組成,同一行或者是同一列之中相鄰的房間的距離為1,我們用(x,y)來表示第x行的第y列的房間,然後KPM驚奇的發現,迷宮的入口(不包含在矩陣狀的房間中)與第一行的所有房間之間都有通道連接,其中與第i個房間連接的通道數目為a(i),然後對於任意兩個房間(x,y),(u,v),當且僅當兩個房間之間的曼哈頓距離不大於k且處於相鄰的兩行,即|x-u|+|y-v|<=k,且|x-u|=1,房間直接存在通道連接,然後根據KPM第XX定律,KPM發現對於入口到第一行房間的所有通道,KPM只能通過其從入口走向房間,卻沒辦法反過來走,對於兩個房間(x,y),(u,v),假如兩個房間之間存在連邊,KPM只能從行數小的那行走到行數大的那行,而且還要保證他走過的房間的列數是單調不遞減的,而且,這如果這兩個房間之間的曼哈頓距離為d,這兩個房間的直接相連通道數目為b(d),也就是說,假如KPM可以從(x,y)走到(u,v),必須有u=x+1,v>=y,且從(x,y)到(u,v)總共有b(v-y+1)條通道直接連接。現在,KPM無聊的想知道,從入口出發,到達第n行的第i個房間,他總共有多少種走法,由於他有數字恐懼癥,所以你只需要告訴他答案對19取模的結果即可。

Input

輸入第一行包括三個整數n,m,k;
輸入第二行包括m個整數,其中第i個整數為a(i);
輸入第三行包括k個整數,其中第i個整數為b(i)。

Output


輸出包括一行,該行包括m個整數,其中第i個整數表示從入口到達(n,i)的方案數對19的取模(註意:只要經過的直接通路序列不同即算成不同方案)。

Sample Input

3 2 2
3 4
1 2

Sample Output

3 16

解題思路:

考慮只能往下走,和往右下走,每一行的每一處的轉移方案都可以認為是上一行的某處方案×$b_{曼哈頓距離}$

所以可以認為是a數組上乘了n-1個b數組,n太大多項式快速冪解決就好了。

PS:以前沒做過這類題目FFT中m項以後的數都是要刪除的否則會一下答案。

代碼:

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 typedef long long lnt;
 6 const int N=1031073;
 7 const double PI=acos(-1.0);
 8 struct cp{
 9     double x,y;cp(){};cp(double a,double b){x=a;y=b;}
10 cp friend operator + (cp a,cp b){return cp(a.x+b.x,a.y+b.y);} 11 cp friend operator - (cp a,cp b){return cp(a.x-b.x,a.y-b.y);} 12 cp friend operator * (cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);} 13 }B[N],C[N]; 14 lnt n; 15 int m,k; 16 int lim,len; 17 int pos[N]; 18 int Aa[N],Bb[N]; 19 void FFT(cp *a,double flag) 20 { 21 for(int i=0;i<len;i++) 22 if(i<pos[i]) 23 std::swap(a[i],a[pos[i]]); 24 for(int i=2;i<=len;i<<=1) 25 { 26 cp wn(cos(2.00*PI*flag/(double)(i)),sin(2.00*PI*flag/(double)(i))); 27 for(int j=0;j<len;j+=i) 28 { 29 cp w(1.00,0.00),t; 30 for(int k=0;k<(i>>1);k++,w=w*wn) 31 { 32 t=a[j+k+(i>>1)]*w; 33 a[j+k+(i>>1)]=a[j+k]-t; 34 a[j+k]=a[j+k]+t; 35 } 36 } 37 } 38 return ; 39 } 40 int main() 41 { 42 scanf("%lld%d%d",&n,&m,&k); 43 memset(Bb,0,sizeof(Bb)); 44 for(int i=1;i<=m;i++)scanf("%d",&Aa[i]); 45 for(int i=0;i<k;i++)scanf("%d",&Bb[i]); 46 if(n==1) 47 { 48 for(int i=1;i<=m;i++)printf("%d ",Aa[i]); 49 return 0; 50 } 51 while((1<<lim)<=2*m)lim++; 52 len=1<<lim; 53 for(int i=0;i<len;i++)pos[i]=(pos[i>>1]>>1)|((i&1)<<(lim-1)); 54 for(int i=0;i<=m;i++) 55 { 56 C[i].x=Aa[i]; 57 B[i].x=Bb[i]; 58 } 59 n--; 60 while(n) 61 { 62 if(n&1) 63 { 64 FFT(C,1.0); 65 FFT(B,1.0); 66 for(int i=0;i<len;i++)C[i]=C[i]*B[i]; 67 FFT(C,-1.0); 68 FFT(B,-1.0); 69 for(int i=0;i<len;i++) 70 C[i]=cp(((int)(C[i].x/len+0.1))%19,0.00), 71 B[i]=cp(((int)(B[i].x/len+0.1))%19,0.00); 72 } 73 FFT(B,1.0); 74 for(int i=0;i<len;i++)B[i]=B[i]*B[i]; 75 FFT(B,-1.0); 76 for(int i=0;i<len;i++)B[i]=cp(((int)(B[i].x/len+0.1))%19,0.00); 77 for(int i=m+1;i<len;i++)C[i].x=B[i].x=0.00; 78 n=n/2; 79 } 80 for(int i=1;i<=m;i++) 81 printf("%d ",((int(C[i].x+0.1))+19)%19); 82 puts(""); 83 return 0; 84 }

BZOJ3645: Maze(FFT多項式快速冪)