4836: [Lydsy1704月赛]二元运算

Time Limit: 8 Sec  Memory Limit: 128 MB
Submit: 578  Solved: 202
[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

Source

[Submit][Status][Discuss]

挺有意思的一道题,应该不难想到是分治FFT,主要是CDQ分治函数内部要想得很清楚。

首先如果只有加法,就是裸卷积。

如果只有减法,那么有$c_k=\sum\limits_{i=k}^na_ib_{i-k}$,把b翻转,最后将c前移n位即可$c_{n+k}=\sum\limits_{i=0}^na_{k+i}b_{n-i}$

现在有了大小关系的限制,我们可以通过$CDQ$分治处理。

首先特判掉相等的情况,然后对于$[l,r]$这个区间,将$[l,mid]$和$[mid+1,r]$递归处理,现在问题只剩下$a[l,mid]$和$b[mid+1,r]$,$a[mid+1,r]$和$b[l,mid]$两个问题了。

显然前一个问题直接将$a$前移$l$位,$b$前移$mid+1$位,卷起来之后再后移$l+mid+1$位即可。后一个问题,将$a$前移$mid+1$位,b翻转后前移$l$位,这样卷之后的区间下标是从$0$开始的,而我们的差是从$1$开始的,所以右移$1$位。

卷的时候还是一定要注意次数界!NTT也可以。

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define mem(a) memset(a,0,sizeof(a))
  6. typedef long long ll;
  7. using namespace std;
  8.  
  9. const int N=;
  10. const double pi=acos(-.);
  11. struct C{ double x,y; }A[N],B[N];
  12. int a[N],b[N],rev[N],n,T,x,m,Q,mx,len1,len2;
  13. ll ans[N];
  14.  
  15. C operator +(C &a,C &b){ return (C){a.x+b.x,a.y+b.y}; }
  16. C operator -(C &a,C &b){ return (C){a.x-b.x,a.y-b.y}; }
  17. C operator *(const C &a,const C &b){ return (C){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x}; }
  18.  
  19. void DFT(C a[],int n,int f){
  20. for (int i=; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
  21. for (int i=; i<n; i<<=){
  22. C wn=(C){cos(pi/i),f*sin(pi/i)};
  23. for (int p=i<<,j=; j<n; j+=p){
  24. C w=(C){,};
  25. for (int k=; k<i; k++,w=w*wn){
  26. C x=a[j+k],y=w*a[i+j+k]; a[j+k]=x+y; a[i+j+k]=x-y;
  27. }
  28. }
  29. }
  30. if (f==) return;
  31. for (int i=; i<n; i++) a[i].x/=n;
  32. }
  33.  
  34. void CDQ(int l,int r){
  35. if (l==r) return;
  36. int mid=(l+r)>>,n,L=;
  37. for (n=; n<=r-l+; n<<=) L++;
  38. for (int i=; i<n; i++) rev[i]=(rev[i>>]>>)|((i&)<<(L-));
  39.  
  40. for (int i=; i<n; i++) A[i]=B[i]=(C){,};
  41. for (int i=l; i<=mid; i++) A[i-l].x=a[i];
  42. for (int i=mid+; i<=r; i++) B[i-mid-].x=b[i];
  43. DFT(A,n,); DFT(B,n,);
  44. for (int i=; i<n; i++) A[i]=A[i]*B[i];
  45. DFT(A,n,-);
  46. for (int i=; i<n; i++) ans[i+mid++l]+=(ll)(A[i].x+0.5);
  47.  
  48. for (int i=; i<n; i++) A[i]=B[i]=(C){,};
  49. for (int i=mid+; i<=r; i++) A[i-mid-].x=a[i];
  50. for (int i=l; i<=mid; i++) B[mid-i].x=b[i];
  51. DFT(A,n,); DFT(B,n,);
  52. for (int i=; i<n; i++) A[i]=A[i]*B[i];
  53. DFT(A,n,-);
  54. for (int i=; i<n; i++) ans[i+]+=(ll)(A[i].x+0.5);
  55. CDQ(l,mid); CDQ(mid+,r);
  56. }
  57.  
  58. int main(){
  59. freopen("bzoj4836.in","r",stdin);
  60. freopen("bzoj4836.out","w",stdout);
  61. for (scanf("%d",&T); T--; ){
  62. scanf("%d%d%d",&n,&m,&Q); mem(ans); mem(a); mem(b); len1=len2=;
  63. for (int i=; i<=n; i++) scanf("%d",&x),a[x]++,len1=max(len1,x);
  64. for (int i=; i<=m; i++) scanf("%d",&x),b[x]++,len2=max(len2,x);
  65. for (int i=; i<=len1 && i<=len2; i++) ans[]+=1ll*a[i]*b[i];
  66. CDQ(,max(len1,len2));
  67. for (int i=; i<=Q; i++) scanf("%d",&x),printf("%lld\n",ans[x]);
  68. }
  69. return ;
  70. }

[BZOJ4836]二元运算(分治FFT)的更多相关文章

  1. 【bzoj4836】[Lydsy2017年4月月赛]二元运算 分治+FFT

    题目描述 定义二元运算 opt 满足   现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c  你需要求出有多少对 (i, j) 使得 a_ ...

  2. bzoj 4836 [Lydsy1704月赛]二元运算 分治FFT+生成函数

    [Lydsy1704月赛]二元运算 Time Limit: 8 Sec  Memory Limit: 128 MBSubmit: 577  Solved: 201[Submit][Status][Di ...

  3. 【bzoj4836】二元运算 分治FFT

    Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...

  4. bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT

    4836: [Lydsy2017年4月月赛]二元运算 Time Limit: 8 Sec  Memory Limit: 128 MB Description 定义二元运算 opt 满足   现在给定一 ...

  5. BZOJ 4836: [Lydsy1704月赛]二元运算 分治FFT

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 500000 #define setIO(s) freope ...

  6. BZOJ4836 [Lydsy1704月赛]二元运算 分治 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8830036.html 题目传送门 - BZOJ4836 题意 定义二元运算$opt$满足 $$x\ opt\ y ...

  7. BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】

    Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...

  8. BNUOJ 51279[组队活动 Large](cdq分治+FFT)

    传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...

  9. hdu 5730 Shell Necklace [分治fft | 多项式求逆]

    hdu 5730 Shell Necklace 题意:求递推式\(f_n = \sum_{i=1}^n a_i f_{n-i}\),模313 多么优秀的模板题 可以用分治fft,也可以多项式求逆 分治 ...

随机推荐

  1. MySQL增删改查之查询

    (7)范围查询select * from car where price>40 and price<60   --查询价格在40-60之间的select * from car where ...

  2. JS之递归(例题:猴子吃桃)

    例题1:公园里有200个桃子,猴子每天吃掉一半以后扔掉一个,问6天以后还剩余多少桃子? var sum = 200; for(var i= 0;i<6;i++) { sum = parseInt ...

  3. fileinput 小计(显示历史上传图片)

    今天又需要,要求在选中某条记录后显示历史上传图片 上传控件是fileinput.js 想法:界面有上传图片的控件,重新加载控件,并加入历史上传图片地址 实现代码: var filepathArray ...

  4. js_时间戳和时间格式之间的转换。

    关于我的理解,简单明了点: 时间戳:把一个日期使用一个数字表示出来,这个数字就是这个日期的秒数. 日期:就是我们常见的时间表现形式. 时间戳对于一般看时间不够直观明了,可是在程序的世界里作用可大了. ...

  5. Python学习笔记 - day12 - Python操作NoSQL

    NoSQL(非关系型数据库) NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称.用于超大规模数据的存储.(例如 ...

  6. windows7 能连接移动硬盘 无法显示盘符

    右键点我的电脑,管理里,点磁盘管理,看盘认到没,有时候认到了但是没给盘符,需要自己手动给一个

  7. linux 下多版本gcc 共存问题

    linux 下多版本gcc 共存问题 http://blog.csdn.net/isfirst/article/details/42296583 参考 http://blog.csdn.net/chi ...

  8. xtrabackup 安装、备份和恢复

    xtrabackup 版本对应: 2.4 专针对 5.7 开发的,兼容 5.6, 5.5 2.3 针对 5.6 开发的,兼容5.5 2.2 针对5.5 开发的 安装包下载: wget https:// ...

  9. UVALive 7040 Color

    题目链接:LA-7040 题意为用m种颜色给n个格子染色.问正好使用k种颜色的方案有多少. 首先很容易想到的是\( k * (k-1)^{n-1}\),这个算出来的是使用小于等于k种颜色给n个方格染色 ...

  10. 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...