[BZOJ4836]二元运算(分治FFT)
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 5Sample Output
1
0
1
0
0
1
0
1
0
1HINT
Source
挺有意思的一道题,应该不难想到是分治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也可以。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std; const int N=;
const double pi=acos(-.);
struct C{ double x,y; }A[N],B[N];
int a[N],b[N],rev[N],n,T,x,m,Q,mx,len1,len2;
ll ans[N]; C operator +(C &a,C &b){ return (C){a.x+b.x,a.y+b.y}; }
C operator -(C &a,C &b){ return (C){a.x-b.x,a.y-b.y}; }
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}; } void DFT(C a[],int n,int f){
for (int i=; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=; i<n; i<<=){
C wn=(C){cos(pi/i),f*sin(pi/i)};
for (int p=i<<,j=; j<n; j+=p){
C w=(C){,};
for (int k=; k<i; k++,w=w*wn){
C x=a[j+k],y=w*a[i+j+k]; a[j+k]=x+y; a[i+j+k]=x-y;
}
}
}
if (f==) return;
for (int i=; i<n; i++) a[i].x/=n;
} void CDQ(int l,int r){
if (l==r) return;
int mid=(l+r)>>,n,L=;
for (n=; n<=r-l+; n<<=) L++;
for (int i=; i<n; i++) rev[i]=(rev[i>>]>>)|((i&)<<(L-)); for (int i=; i<n; i++) A[i]=B[i]=(C){,};
for (int i=l; i<=mid; i++) A[i-l].x=a[i];
for (int i=mid+; i<=r; i++) B[i-mid-].x=b[i];
DFT(A,n,); DFT(B,n,);
for (int i=; i<n; i++) A[i]=A[i]*B[i];
DFT(A,n,-);
for (int i=; i<n; i++) ans[i+mid++l]+=(ll)(A[i].x+0.5); for (int i=; i<n; i++) A[i]=B[i]=(C){,};
for (int i=mid+; i<=r; i++) A[i-mid-].x=a[i];
for (int i=l; i<=mid; i++) B[mid-i].x=b[i];
DFT(A,n,); DFT(B,n,);
for (int i=; i<n; i++) A[i]=A[i]*B[i];
DFT(A,n,-);
for (int i=; i<n; i++) ans[i+]+=(ll)(A[i].x+0.5);
CDQ(l,mid); CDQ(mid+,r);
} int main(){
freopen("bzoj4836.in","r",stdin);
freopen("bzoj4836.out","w",stdout);
for (scanf("%d",&T); T--; ){
scanf("%d%d%d",&n,&m,&Q); mem(ans); mem(a); mem(b); len1=len2=;
for (int i=; i<=n; i++) scanf("%d",&x),a[x]++,len1=max(len1,x);
for (int i=; i<=m; i++) scanf("%d",&x),b[x]++,len2=max(len2,x);
for (int i=; i<=len1 && i<=len2; i++) ans[]+=1ll*a[i]*b[i];
CDQ(,max(len1,len2));
for (int i=; i<=Q; i++) scanf("%d",&x),printf("%lld\n",ans[x]);
}
return ;
}
[BZOJ4836]二元运算(分治FFT)的更多相关文章
- 【bzoj4836】[Lydsy2017年4月月赛]二元运算 分治+FFT
题目描述 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使得 a_ ...
- bzoj 4836 [Lydsy1704月赛]二元运算 分治FFT+生成函数
[Lydsy1704月赛]二元运算 Time Limit: 8 Sec Memory Limit: 128 MBSubmit: 577 Solved: 201[Submit][Status][Di ...
- 【bzoj4836】二元运算 分治FFT
Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...
- bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT
4836: [Lydsy2017年4月月赛]二元运算 Time Limit: 8 Sec Memory Limit: 128 MB Description 定义二元运算 opt 满足 现在给定一 ...
- BZOJ 4836: [Lydsy1704月赛]二元运算 分治FFT
Code: #include<bits/stdc++.h> #define ll long long #define maxn 500000 #define setIO(s) freope ...
- BZOJ4836 [Lydsy1704月赛]二元运算 分治 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8830036.html 题目传送门 - BZOJ4836 题意 定义二元运算$opt$满足 $$x\ opt\ y ...
- BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】
Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...
- BNUOJ 51279[组队活动 Large](cdq分治+FFT)
传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...
- hdu 5730 Shell Necklace [分治fft | 多项式求逆]
hdu 5730 Shell Necklace 题意:求递推式\(f_n = \sum_{i=1}^n a_i f_{n-i}\),模313 多么优秀的模板题 可以用分治fft,也可以多项式求逆 分治 ...
随机推荐
- 【51NOD-0】1137 矩阵乘法
[算法]简单数学 [题解] 对于A*B=C C中第i行第j列的数字由A中第i行和B中的j列的数字各自相乘后相加得到. 所以两个矩阵能相乘要求A的列数等于B的行数,复杂度为O(n3). #include ...
- 用vue快速开发app的脚手架工具
前言 多页面应用于结构较于简单的页面,因为简答的页面使用router又过于麻烦.本脚手架出于这样的场景被开发出来. 使用脚手架搭配Hbuilder也同样可以快速使用vue开发安卓和IOS APP. 本 ...
- Arduino 舵机sg90电位器实现转动方向控制
/* Sweep*/ #include <Servo.h> int potpin = 0;//电位器接到A0 int val; //存储电位器读取的数值 Servo myservo//定义 ...
- Git常规配置与基本用法
Git环境配置 一. 全局配置 1. 配置文件 git全局配置文件.gitconfig默认在当前系统用户文件夹下,window可运行%USERPROFILE%查找,Mac系统在cd ~查找. 具体配置 ...
- IoT之车联网
一. 背景 这是一个笔者在实习公司策划的关于车联网的小项目,也是笔者参加某竞赛的作品<基于云平台的车内滞留儿童状况监测与处理>,本项目旨在为因各种原因导致儿童滞留车内热死.闷死的社会性事件 ...
- springboot基础知识学习
一.springboot中常用的注解: 原文链接:http://blog.csdn.net/lafengwnagzi/article/details/53034369 原文链接:http://www. ...
- 获取windows 网卡GUID和ip信息
# coding: UTF-8 import _winreg GUID=dict() num = 0 netCfgInstanceID = None hkey = _winreg.OpenKey(_w ...
- f1 f12热键关闭
fn+f2进入bios系统——>找到configuration——>Hotkey Mode——>enter——>选择disable——>fn+f10保存
- echo常用操作
echo -n 不换行输出 [root@C ~]# echo -n "peter" ; echo "linux" peterlinux echo -e 输出转义 ...
- ASP.NET Core学习链接
https://www.cnblogs.com/artech/p/dependency-injection-in-asp-net-core.html http://www.cnblogs.com/ar ...