1. 程式人生 > >bzoj 4836 [Lydsy1704月賽]二元運算 分治FFT+生成函數

bzoj 4836 [Lydsy1704月賽]二元運算 分治FFT+生成函數

AI gre add def mar sans 成了 while sizeof

[Lydsy1704月賽]二元運算

Time Limit: 8 Sec Memory Limit: 128 MB
Submit: 577 Solved: 201
[Submit][Status][Discuss]

Description

定義二元運算 opt 滿足 技術分享圖片 現在給定一個長為 n 的數列 a 和一個長為 m 的數列 b ,接下來有 q 次詢問。每次詢問給定一個數字 c 你需要求出有多少對 (i, j) 使得 a_i opt b_j=c 。

Input

第一行是一個整數 T (1≤T≤10) ,表示測試數據的組數。 對於每組測試數據: 第一行是三個整數 n,m,q (1≤n,m,q≤50000) 。 第二行是 n 個整數,表示 a_1,a_2,?,a_n (0≤a_1,a_2,?,a_n≤50000) 。 第三行是 m 個整數,表示 b_1,b_2,?,b_m (0≤b_1,b_2,?,b_m≤50000) 。 第四行是 q 個整數,第 i 個整數 c_i (0≤c_i≤100000) 表示第 i 次查詢的數。

Output

對於每次查詢,輸出一行,包含一個整數,表示滿足條件的 (i, j) 對的個數。

Sample Input

2
2 1 5
1 3
2
1 2 3 4 5
2 2 5
1 3
2 4
1 2 3 4 5

Sample Output

1
0
1
0
0
1
0
1
0
1

HINT

這道題就是分治fft的生成函數題,加法應該很好辦,但是減法怎麽辦,就是將其變成加法就可以了。

減法的時候,對於x-y,變成x-mid-1,mid-y,這樣就相加就變成了x-y-1,最後把1加上去就可以了。

  1 #include<cstring>
  2
#include<cmath> 3 #include<algorithm> 4 #include<cstdio> 5 #include<iostream> 6 7 #define pi acos(-1) 8 #define ll long long 9 #define N 100007 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if
(ch==-)f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,q,mx; 20 int a[N],b[N],rev[N<<1]; 21 ll ans[N]; 22 struct comp 23 { 24 double r,v; 25 comp(){r=v=0.0;} 26 comp(double x,double y){r=x,v=y;} 27 void init(){r=v=0.0;} 28 friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);} 29 friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);} 30 friend inline comp operator*(comp x,comp y){return comp(x.r*y.r-x.v*y.v,x.r*y.v+x.v*y.r);} 31 friend inline comp operator/(comp x,int y){return comp(x.r/y,x.v/y);} 32 }c[N<<1],d[N<<1]; 33 34 void FFT(comp *a,int flag,int num) 35 { 36 for (int i=0;i<num;i++) 37 if (i<rev[i]) swap(a[i],a[rev[i]]); 38 for (int i=1;i<num;i<<=1) 39 { 40 comp wn=comp(cos(pi/i),flag*sin(pi/i)); 41 for (int j=0;j<num;j+=(i<<1)) 42 { 43 comp w=comp(1,0); 44 for (int k=0;k<i;k++,w=w*wn) 45 { 46 comp x=a[j+k],y=w*a[i+j+k]; 47 a[j+k]=x+y,a[j+k+i]=x-y; 48 } 49 } 50 } 51 if (flag==-1) for (int i=0;i<num;i++) a[i].r=a[i].r/num; 52 } 53 void CDQ(int l,int r) 54 { 55 if (l==r) 56 { 57 ans[0]+=(ll)a[l]*b[l]; 58 return; 59 } 60 int mid=(l+r)>>1,num,up=r-l+1,L=0; 61 for (num=1;num<=up;num<<=1,L++);if (L) L--; 62 for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L); 63 64 memset(c,0,sizeof(c[0])*num),memset(d,0,sizeof(d[0])*num); 65 for (int i=l;i<=mid;i++) c[i-l].r=a[i]; 66 for (int i=mid+1;i<=r;i++) d[i-mid-1].r=b[i]; 67 FFT(c,1,num),FFT(d,1,num); 68 for (int i=0;i<num;i++) c[i]=c[i]*d[i]; 69 FFT(c,-1,num); 70 for (int i=0;i<num;i++) ans[i+l+mid+1]+=(ll)(c[i].r+0.5); 71 72 memset(c,0,sizeof(c[0])*num),memset(d,0,sizeof(d[0])*num); 73 for (int i=mid+1;i<=r;i++) c[i-mid-1].r=a[i]; 74 for (int i=l;i<=mid;i++) d[mid-i].r=b[i]; 75 FFT(c,1,num),FFT(d,1,num); 76 for (int i=0;i<num;i++) c[i]=c[i]*d[i]; 77 FFT(c,-1,num); 78 for (int i=0;i<num;i++) ans[i+1]+=(ll)(c[i].r+0.5); 79 80 CDQ(l,mid),CDQ(mid+1,r); 81 } 82 int main() 83 { 84 int T=read(); 85 while(T--) 86 { 87 n=read(),m=read(),q=read(); 88 memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(ans,0,sizeof(ans)); 89 for (int i=1;i<=n;i++) 90 { 91 int x=read(); 92 a[x]++,mx=max(mx,x); 93 } 94 for (int i=1;i<=m;i++) 95 { 96 int x=read(); 97 b[x]++,mx=max(mx,x); 98 } 99 CDQ(0,mx); 100 for (int i=1;i<=q;i++) 101 printf("%lld\n",ans[read()]); 102 } 103 }

#include<cstring>#include<cmath>#include<algorithm>#include<iostream>#include<cstdio>
#define pi acos(-1)#define N 600007using namespace std;inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}return x*f;}
int R,C,H,W,num,L;int rev[N],a[507][507],b[507][507];struct comp{double r,v;comp(){r=v=0.0;}comp(double x,double y){r=x,v=y;}void init(){r=v=0.0;}friend inline comp operator+(comp x,comp y){return comp(x.r+y.r,x.v+y.v);}friend inline comp operator-(comp x,comp y){return comp(x.r-y.r,x.v-y.v);}friend inline comp operator*(comp x,comp y){return comp(x.r*y.r-x.v*y.v,x.r*y.v+x.v*y.r);}friend inline comp operator/(comp x,int y){return comp(x.r/y,x.v/y);}}a1[N],b1[N],a2[N],b2[N],c[N];char ch[507],T[507][507];
void FFT(comp *a,int flag){for (int i=0;i<num;i++)if (i<rev[i]) swap(a[i],a[rev[i]]);for (int i=1;i<num;i<<=1){comp wn=comp(cos(pi/i),flag*sin(pi/i));for (int j=0;j<num;j+=(i<<1)){comp w=comp(1,0);for (int k=0;k<i;k++,w=w*wn){comp x=a[j+k],y=w*a[j+k+i];a[j+k]=x+y,a[j+k+i]=x-y;}}}if (flag==-1) for (int i=0;i<num;i++) a[i].r=a[i].r/num;}int main(){R=read(),C=read();for (int i=0;i<R;i++){scanf("%s",ch);for (int j=0;j<C;j++){if (ch[j]==‘G‘) a1[i*C+j]=comp(1,0);else b1[i*C+j]=comp(1,0);}}for (num=1;num<=R*C*2;num<<=1,L++);if (L) L--;for (int i=0;i<num;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<L);FFT(a1,1),FFT(b1,1);int Total=read();for (int Case=1;Case<=Total;Case++){H=read(),W=read(),memset(a,0,sizeof(a)),memset(b,0,sizeof(b));for (int i=0;i<num;i++)a2[i].init(),b2[i].init();for (int i=0;i<H;i++)scanf("%s",T[i]);for (int i=0;i<H;i++)for (int j=0;j<W;j++)if (T[i][j]==‘G‘) a2[R*C-1-i*C-j]=comp(1,0);else b2[R*C-1-i*C-j]=comp(1,0);FFT(a2,1),FFT(b2,1);for (int i=0;i<num;i++)a2[i]=a1[i]*a2[i],b2[i]=b1[i]*b2[i];FFT(a2,-1),FFT(b2,-1);for (int i=0;i<R-H;i++)for (int j=0;j<C-W;j++)a[i][j]=(int)(a2[i*C+j+R*C-1].r+0.5),b[i][j]=(int)(b2[i*C+j+R*C-1].r+0.5);int x,y;x=y=0;for (int i=0;i<R-H;i++)for (int j=0;j<=C-W;j++)if (a[i][j]+b[i][j]>a[x][y]+b[x][y]) x=i,y=j;printf("Case #%d: %d %d %d %d\n",Case,x+1,y+1,a[x][y],b[x][y]);}}

bzoj 4836 [Lydsy1704月賽]二元運算 分治FFT+生成函數