题目

Source

http://vjudge.net/problem/142058

Description

Given N integers A1, A2, …. AN, Dexter wants to know how many ways he can choose three numbers such that they are three consecutive terms of an arithmetic progression.

Meaning that, how many triplets (i, j, k) are there such that 1 ≤ i < j < k ≤ N and Aj - Ai = Ak - Aj.

So the triplets (2, 5, 8), (10, 8, 6), (3, 3, 3) are valid as they are three consecutive terms of an arithmetic
progression. But the triplets (2, 5, 7), (10, 6, 8) are not.

Input

First line of the input contains an integer N (3 ≤ N ≤ 100000). Then the following line contains N space separated integers A1, A2, …, AN and they have values between 1 and 30000 (inclusive).

Output

Output the number of ways to choose a triplet such that they are three consecutive terms of an arithmetic progression.

Sample Input

10
3 5 3 6 3 4 10 4 5 2

Sample Output

9

分析

题目大概说给一个长N的序列A,问有多少个三元组<i,j,k>满足i<j<k且Ai+Ak=2Aj。

i<j<k这个关系不好搞,正解好像是分块:

  • 把序列分解成若干块,每一块长度大约为B。分三种情况考虑:
  1. 对于三个都在同一块的:枚举各个块,然后通过枚举i和k并更新记录j的信息求出对数。时间复杂度$O(N/B\times B\times B)=O(NB)$。
  2. 对于只有两个在同一块的:枚举各个块,并更新记录前面所有块和后面所有块的信息,然后枚举块内的两个数,另一个数可能在块前也可能在块后,这样求出对数。时间复杂度$O(N/B\times B\times B)=O(NB)$。
  3. 对于三个数都在不同块的:枚举各个块,并更新记录前面所有块和后面所有块的信息,然后构造多项式用FFT求出前后两边组合成各个和的方案数,通过枚举块内的j即可求出对数。时间复杂度$O(N/B\times 65535\times 16+N/B\times B)$
  • 然后就是B大小的设定,我设定的是$5\sqrt N$。
  • 最后我连枚举都不会枚举。。还有有个地方只考虑是否大于0,没考虑是否小于等于30000,数组越界,WA了好久。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 66666
const double PI=acos(-1.0); struct Complex{
double real,imag;
Complex(double _real,double _imag):real(_real),imag(_imag){}
Complex(){}
Complex operator+(const Complex &cp) const{
return Complex(real+cp.real,imag+cp.imag);
}
Complex operator-(const Complex &cp) const{
return Complex(real-cp.real,imag-cp.imag);
}
Complex operator*(const Complex &cp) const{
return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
}
void setValue(double _real=0,double _imag=0){
real=_real; imag=_imag;
}
}; int len;
Complex wn[MAXN],wn_anti[MAXN]; void FFT(Complex y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
for(int h=2; h<=len; h<<=1){
Complex Wn=(op==1?wn[h]:wn_anti[h]);
for(int i=0; i<len; i+=h){
Complex W(1,0);
for(int j=i; j<i+(h>>1); ++j){
Complex u=y[j],t=W*y[j+(h>>1)];
y[j]=u+t;
y[j+(h>>1)]=u-t;
W=W*Wn;
}
}
}
if(op==-1){
for(int i=0; i<len; ++i) y[i].real/=len;
}
}
void Convolution(Complex A[],Complex B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i].setValue();
B[i].setValue();
} FFT(A,1); FFT(B,1);
for(int i=0; i<len; ++i){
A[i]=A[i]*B[i];
}
FFT(A,-1);
} int a[111111];
int cnt[33100],cnt0[33100],cnt1[33100];
Complex A[MAXN],B[MAXN]; int main(){
for(int i=0; i<MAXN; ++i){
wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
wn_anti[i].setValue(wn[i].real,-wn[i].imag);
}
int n;
while(~scanf("%d",&n)){
for(int i=0; i<n; ++i){
scanf("%d",a+i);
}
int block=(int)(sqrt(n)+1e-6)*5; long long ans=0; for(int b=0; b<n; b+=block){
for(int i=0; i<block && b+i<n; ++i){
for(int j=i+1; j<block && b+j<n; ++j){
int tmp=a[b+i]+a[b+j];
if((tmp&1)==0){
ans+=cnt[tmp>>1];
}
++cnt[a[b+j]];
}
for(int j=i+1; j<block && b+j<n; ++j){
--cnt[a[b+j]];
}
}
} memset(cnt0,0,sizeof(cnt0));
memset(cnt1,0,sizeof(cnt1));
for(int i=0; i<n; ++i){
++cnt1[a[i]];
}
for(int b=0; b<n; b+=block){
for(int i=0; i<block && b+i<n; ++i){
--cnt1[a[b+i]];
}
for(int i=0; i<block && b+i<n; ++i){
for(int j=i+1; j<block && b+j<n; ++j){
int tmp=a[b+i]*2-a[b+j];
if(tmp>0 && tmp<=30000) ans+=cnt0[tmp];
tmp=a[b+j]*2-a[b+i];
if(tmp>0 && tmp<=30000) ans+=cnt1[tmp];
}
}
for(int i=0; i<block && b+i<n; ++i){
++cnt0[a[b+i]];
}
} memset(cnt0,0,sizeof(cnt0));
memset(cnt1,0,sizeof(cnt1));
for(int i=0; i<n; ++i){
++cnt1[a[i]];
}
for(int b=0; b<n; b+=block){
for(int i=0; i<block && b+i<n; ++i){
--cnt1[a[b+i]];
} for(int i=0; i<=30000; ++i){
A[i].setValue(cnt0[i]);
B[i].setValue(cnt1[i]);
}
Convolution(A,B,30001);
for(int i=0; i<block && b+i<n; ++i){
ans+=(long long)(A[a[b+i]<<1].real+0.5);
} for(int i=0; i<block && b+i<n; ++i){
++cnt0[a[b+i]];
}
} printf("%lld\n",ans);
}
return 0;
}

CodeChef COUNTARI Arithmetic Progressions(分块 + FFT)的更多相关文章

  1. CodeChef - COUNTARI Arithmetic Progressions (FFT)

    题意:求一个序列中,有多少三元组$(i,j,k)i<j<k $ 满足\(A_i + A_k = 2*A_i\) 构成等差数列. https://www.cnblogs.com/xiuwen ...

  2. [BZOJ 3509] [CodeChef] COUNTARI (FFT+分块)

    [BZOJ 3509] [CodeChef] COUNTARI (FFT+分块) 题面 给出一个长度为n的数组,问有多少三元组\((i,j,k)\)满足\(i<j<k,a_j-a_i=a_ ...

  3. CC countari & 分块+FFT

    题意: 求一个序列中顺序的长度为3的等差数列. SOL: 对于这种计数问题都是用个数的卷积来进行统计.然而对于这个题有顺序的限制,不好直接统计,于是竟然可以分块?惊为天人... 考虑分块以后的序列: ...

  4. bzoj 3509: [CodeChef] COUNTARI] [分块 生成函数]

    3509: [CodeChef] COUNTARI 题意:统计满足\(i<j<k, 2*a[j] = a[i] + a[k]\)的个数 \(2*a[j]\)不太好处理,暴力fft不如直接暴 ...

  5. CodeChef - COUNTARI FTT+分块

    Arithmetic Progressions Given N integers A1, A2, …. AN, Dexter wants to know how many ways he can ch ...

  6. BZOJ 3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 883  Solved: 250[Submit][S ...

  7. BZOJ3509: [CodeChef] COUNTARI

    3509: [CodeChef] COUNTARI Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 85[Submit][St ...

  8. [Educational Codeforces Round 16]D. Two Arithmetic Progressions

    [Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...

  9. Dirichlet's Theorem on Arithmetic Progressions 分类: POJ 2015-06-12 21:07 7人阅读 评论(0) 收藏

    Dirichlet's Theorem on Arithmetic Progressions Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

随机推荐

  1. ztree.js的使用整理

    /** 配置:知识点管理 */ var setting = { view: { showIcon: false, addDiyDom: addPrevDom, addHoverDom: addHove ...

  2. 树莓派系统介绍:DIetPi

    项目主页:http://fuzon.co.uk/phpbb/viewtopic.php?f=8&t=6 当前版本:V34(15年4月16日发布) DietPi是国外一个基于Raspbian的精 ...

  3. JSP登录页面使用Enter键登录【转】

    按回车键实现登录   第一种方法:        <html xmlns="http://www.w3.org/1999/xhtml" ><head>  & ...

  4. springmvc @PathVariable("b") double b 丢失精度问题

    Spring MVC从3.0开始支持REST,而主要就是通过@PathVariable来处理请求参数和路径的映射.由于考虑到SEO的缘故,很多人喜欢把新闻的名称作为路径中的一部分去处理,这时候中文的名 ...

  5. 英文写作——冠词的使用(Use 0f Articles)

    1.使用'a','an','the'和不使用冠词的基本规则: <1>泛指,不可数名词不能有任何冠词 <2>泛指,可数,复数名词前不能有冠词 <3>泛指,可数,单数名 ...

  6. php多进程总结

    本文部分来自网络参考,部分自己总结,由于一直保存在笔记中,并没有记录参考文章地址,如有侵权请通知删除.最近快被业务整疯了,这个等抽时间还需要好好的整理一番.   多进程--fork 场景:日常任务中, ...

  7. 关于linux asp.net MVC网站中 httpHandlers配置无效的处理方法

    近期有Jexus用户反映,在Linux ASP.NET MVC网站的Web.config中添加 httpHandlers 配置用于处理自定义类型,但是在运行中并没有产生预期的效果,服务器返回了404( ...

  8. Path Sum

    需如下树节点求和 5  /  \ 4     8  /     /  \ 11  13    4 / \     /  \  7    2      5   1 JavaScript实现 window ...

  9. 获取APP最新版本的接口案例

    思路: 开发初期.安卓的应用可能没有上传到应用市场,可以把应用apk放到服务器上,供用户下载.把对应用的版本信息整理成为一个XML文件,放到服务器上,通过接口读取xml文件,获取有版本信息,然后安卓端 ...

  10. 在MySQL向表中插入中文时,出现:incorrect string value 错误

    在MySQL向表中插入中文时,出现:incorrect string value 错误,是由于字符集不支持中文.解决办法是将字符集改为GBK,或UTF-8.      一.修改数据库的默认字符集   ...