1. 程式人生 > >UVA 12633 Super Rooks on Chessboard (生成函數+FFT)

UVA 12633 Super Rooks on Chessboard (生成函數+FFT)

ini nbsp scan fft 格子 esp pan lan int()

題面傳送門

題目大意:給你一張網格,上面有很多騎士,每個騎士能橫著豎著斜著攻擊一條直線上的格子,求沒被攻擊的格子的數量總和

好神奇的卷積

假設騎士不能斜著攻擊

那麽答案就是沒被攻擊的 行數*列數

接下來考慮斜著攻擊對答案的貢獻

以左下角為坐標原點建立坐標系,發現一條對角線的點的$(x+y)$坐標是相同的

考慮卷積,設計兩個生成函數$a,b$

如果第i行沒騎士,則$a_{i}=1$,反之為$0$

如果第i列沒騎士,則$b_{i}=1$,反之為$0$

我們對兩個式子進行卷積,可以求出每一條對角線上還有多少個空格子

答案就是$\sum$ 沒有騎士的對角線的空格子數

 1
#include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define N1 (1<<18) 6 #define M1 (N1<<1) 7 #define ll long long 8 #define dd double 9 #define idx(X) (X-‘a‘) 10 using namespace std; 11 12 int gint() 13 { 14 int
ret=0,fh=1; char c=getchar(); 15 while(c<0||c>9){if(c==-)fh=-1;c=getchar();} 16 while(c>=0&&c<=9){ret=ret*10+c-0;c=getchar();} 17 return ret*fh; 18 } 19 int T,n,m,num,r[N1]; 20 int nt[N1],x[N1],y[N1]; 21 const dd pi=acos(-1); 22 23 struct cp{ 24 dd x,y;
25 friend cp operator + (const cp &s1,const cp &s2){ return (cp){s1.x+s2.x,s1.y+s2.y}; } 26 friend cp operator - (const cp &s1,const cp &s2){ return (cp){s1.x-s2.x,s1.y-s2.y}; } 27 friend cp operator * (const cp &s1,const cp &s2){ return (cp){s1.x*s2.x-s1.y*s2.y,s1.y*s2.x+s1.x*s2.y}; } 28 }a[N1],b[N1],c[N1]; 29 30 void init() 31 { 32 memset(a,0,sizeof(a)); 33 memset(b,0,sizeof(b)); 34 memset(c,0,sizeof(c)); 35 memset(nt,0,sizeof(nt)); 36 } 37 void FFT(cp *s,int len,int type) 38 { 39 int i,j,k; cp wn,w,t; 40 for(i=0;i<len;i++) if(i<r[i]) swap(s[i],s[r[i]]); 41 for(k=2;k<=len;k<<=1) 42 { 43 wn=(cp){cos(2.0*type*pi/k),sin(2.0*type*pi/k)}; 44 for(i=0;i<len;i+=k) 45 { 46 w=(cp){1,0}; 47 for(j=0;j<(k>>1);j++,w=w*wn) 48 { 49 t=w*s[i+j+(k>>1)]; 50 s[i+j+(k>>1)]=s[i+j]-t; 51 s[i+j]=s[i+j]+t; 52 } 53 } 54 } 55 } 56 void FFT_Main(int len) 57 { 58 FFT(a,len,1); FFT(b,len,1); 59 for(int i=0;i<len;i++) c[i]=a[i]*b[i]; 60 FFT(c,len,-1); 61 for(int i=0;i<len;i++) c[i].x=c[i].x/len; 62 } 63 64 int main() 65 { 66 scanf("%d",&T); int t; 67 for(t=1;t<=T;t++){ 68 69 init(); 70 scanf("%d%d%d",&n,&m,&num); 71 int i,j,de,len,L; ll ans=0; 72 for(i=1;i<=num;i++) x[i]=n-gint(), y[i]=gint()-1, a[x[i]].x=-1, b[y[i]].x=-1, nt[x[i]+y[i]]=1; 73 for(i=0;i<n;i++) a[i].x++; 74 for(i=0;i<m;i++) b[i].x++; 75 for(len=1,L=0;len<n+m-1;len<<=1,L++); 76 for(i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1)); 77 FFT_Main(len); 78 for(i=0;i<=n+m-2;i++) if(!nt[i]) ans+=(int)(c[i].x+0.1); 79 printf("Case %d: %lld\n",t,ans); 80 81 } 82 return 0; 83 }

UVA 12633 Super Rooks on Chessboard (生成函數+FFT)