https://www.codechef.com/status/COUNTARI

题意:

给出n个数,求满足i<j<k且a[j]-a[i]==a[j]-a[k] 的三元组(i,j,k)的个数

n^2 做法:

枚举j和k,当j右移时,令sum[num[右移之前j的值]]++

每次统计sum[num[j]*2-num[k]]即可

如果没有i<j<k,直接上FFT

但是有了这个限制,可以枚举j,再FFT,复杂度为n*n*log(30000)

考虑一次FFT只算1个j有点儿浪费

能不能算好几个j?

分块!

设每一块的大小为S

答案分三种:

一、3个数都在一个块

用平方复杂度的做法,枚举同一块内的j和k,总时间复杂度为O(n/S*S*S)=O(n*S)

二、2个数在两个块

如果在同一块的数是j和k,从第一块开始枚举j和k,记录前面块的sum,累加sum[num[j]*2-num[k]]

如果在同一块的数是i和j,从最后一块开始枚举i和j,记录后面块的sum,累加sum[num[j]*2-num[i]]

总时间复杂度为O(n/S*S*S)=O(n*S)

三、3个数在三个块

枚举中间的的那一块,sumL记录这个块左边所有数,sumR记录这个块右边所有数

用FFT对sumL和sumR做一次卷积,得到sum

枚举中间那一块的每个数j,累加sum[num[j]*2]

FFT的一个小细节:

不能出现次数为0的项,所以所有数向左移一位,所以最后得到的sum向左移了两位,实际累加sum[num[j]*2-2]

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> using namespace std; #define N 100001
#define M 30001
#define S 500 const int K=(<<)+; typedef long long LL; const double pi=acos(-); int n,mx,a[N]; int l[M],r[M]; int len=,rev[K]; struct Complex
{
double x,y;
Complex(double x_=,double y_=):x(x_),y(y_){}
Complex operator + (Complex P)
{
return Complex(x+P.x,y+P.y);
}
Complex operator - (Complex P)
{
return Complex(x-P.x,y-P.y);
}
Complex operator * (Complex P)
{
return Complex(x*P.x-y*P.y,x*P.y+y*P.x);
}
};
typedef Complex E; E A[K],B[K]; LL ans; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void fft(E *a,int ty)
{
for(int i=;i<len;++i)
if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=;i<len;i<<=)
{
E wn(cos(pi/i),ty*sin(pi/i));
for(int p=i<<,j=;j<len;j+=p)
{
E w(,);
for(int k=;k<i;++k,w=w*wn)
{
E x=a[j+k],y=a[j+k+i]*w;
a[j+k]=x+y; a[j+k+i]=x-y;
}
}
}
if(ty==-)
{
for(int i=;i<len;++i) a[i].x=a[i].x/len+0.5;
}
} void three()
{
int num=mx*-,bit=;
while(len<=num) len<<=,bit++;
for(int i=;i<len;++i) rev[i]=(rev[i>>]>>)|((i&)<<bit-);
for(int i=;i<=n;++i) r[a[i]]++;
int ed;
for(int t=;t<=n;t+=S)
{
ed=min(n,t+S-);
for(int i=t;i<=ed;++i) r[a[i]]--;
for(int i=;i<mx;++i) A[i].x=l[i+],A[i].y=;
for(int i=mx;i<len;++i) A[i].x=A[i].y=;
fft(A,);
for(int i=;i<mx;++i) B[i].x=r[i+],B[i].y=;
for(int i=mx;i<len;++i) B[i].x=B[i].y=;
fft(B,);
for(int i=;i<len;++i) A[i]=A[i]*B[i];
fft(A,-);
for(int i=t;i<=ed;++i) ans+=A[(a[i]<<)-].x;
for(int i=t;i<=ed;++i) l[a[i]]++;
}
memset(l,,sizeof(l));
} void two()
{
int ed;
for(int t=;t<=n;t+=S)
{
ed=min(n,t+S-);
for(int j=t;j<ed;++j)
for(int k=j+;k<=ed;++k)
if(a[j]<<>a[k] && (a[j]<<)-a[k]<=mx) ans+=l[(a[j]<<)-a[k]];
for(int i=t;i<=ed;++i) l[a[i]]++;
}
memset(l,,sizeof(l));
int t=,st;
while(t<n) t+=S;
t-=S;
for(int i=t+;i<=n;++i) r[a[i]]++;
for(;t>;t-=S)
{
st=t-S+;
for(int i=st;i<t;++i)
for(int j=i+;j<=t;++j)
if(a[j]<<>a[i] && (a[j]<<)-a[i]<=mx) ans+=r[(a[j]<<)-a[i]];
for(int i=st;i<=t;++i) r[a[i]]++;
}
} void one()
{
int ed;
for(int t=;t<=n;t+=S)
{
ed=min(t+S-,n);
for(int j=t;j<=ed;++j)
{
for(int k=j+;k<=ed;++k)
if(a[j]<<>a[k] && (a[j]<<)-a[k]<=mx) ans+=l[(a[j]<<)-a[k]];
l[a[j]]++;
}
for(int j=t;j<=ed;++j) l[a[j]]--;
}
} int main()
{
read(n);
for(int i=;i<=n;++i) read(a[i]),mx=max(mx,a[i]);
three();
two();
one();
cout<<ans;
}

CodeChef Arithmetic Progressions的更多相关文章

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

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

  2. 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 ...

  3. 洛谷P1214 [USACO1.4]等差数列 Arithmetic Progressions

    P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题 ...

  4. POJ 3006 Dirichlet's Theorem on Arithmetic Progressions (素数)

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

  5. poj 3006 Dirichlet's Theorem on Arithmetic Progressions【素数问题】

    题目地址:http://poj.org/problem?id=3006 刷了好多水题,来找回状态...... Dirichlet's Theorem on Arithmetic Progression ...

  6. (素数求解)I - Dirichlet&#39;s Theorem on Arithmetic Progressions(1.5.5)

    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit cid=1006#sta ...

  7. USACO 1.4 Arithmetic Progressions

    Arithmetic Progressions An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb ...

  8. Educational Codeforces Round 16 D. Two Arithmetic Progressions (不互质中国剩余定理)

    Two Arithmetic Progressions 题目链接: http://codeforces.com/contest/710/problem/D Description You are gi ...

  9. 等差数列Arithmetic Progressions题解(USACO1.4)

    Arithmetic Progressions USACO1.4 An arithmetic progression is a sequence of the form a, a+b, a+2b, . ...

随机推荐

  1. Linux CentOS虚拟机网卡配置

    最近在VMware安装CentOS6.5之后,每次从宿主机访问虚拟机的Oracle时,都要修改IP地址,因为没有设置虚拟机的IP,所以每次开机之后虚拟机的IP地址都是随机的,于是研究了下给虚拟机配置静 ...

  2. VMMAP的简单使用

    1. dotnet.exe 进程占用内存非常疯狂.. 开发同事 提供了一个工具进行简单分析 vmmap.exe 执行了 Ctrl+E 之后 发现将 heap 和managed heap 的内容放到了p ...

  3. 文件系统的block 数据库中的block 以及内存中的page基础知识汇总(自己理解 可能有误)

    1. 操作系统文件系统中的的block 文件系统中的block 是文件系统最小的读写单元,在HDD的磁盘时代, 一般block的大小可能与磁盘的扇区大小一致为 512bytes 也因为这个原因MBR启 ...

  4. Fantacy团队周二站立会议

    词频分析模型 1.这次站会是周二开的,但是由于我个人的疏忽,哎,不说了. 2.会议时间:2016年3月29日12:03~12:30. 持续时长:27分钟 会议参加成员:组长:杨若鹏 http://ww ...

  5. pandas分组group

    Pandas对象可以分成任何对象.有多种方式来拆分对象,如 - obj.groupby(‘key’) obj.groupby([‘key1’,’key2’]) obj.groupby(key,axis ...

  6. 几种实现one-hot编码的方式

    方法1 之前写使用sklearn进行数据挖掘-房价预测(4)-数据预处理一文中处理标签类特征时候已经提到过,使用sklearn中提供的LabelEncoder和OneHotEncoder方法 a = ...

  7. Delphi 2010 3513正式版破解

    Delphi 2010 3513正式 一.下载ISO文件右键迅雷下载 二.安装完成后,先运行一下程序,程序会弹出叫你注册对话框,逐步点击Cancel---->OK----->No----& ...

  8. 如何取消浏览器护眼色 Lodop打印图片有窗口颜色的边框

    Lodop打印图片出现了边框,然而通常情况下是没有边框的,由于Lodop是基于本机的ie进行解析的,和IE的设置有关.用户的电脑和习惯千差万别,有人喜欢给浏览器加上护眼色,而这一个行为可能导致Lodo ...

  9. LAMP和LNMP去除index.php访问

    使用TP或者Laravel开发的时候,后时候会遇到需要加index.php才能正常访问 LAMP解决方法 1.修改配置 打开配置文件(如:httpd.conf),找到你网站根目录的配置,将AllowO ...

  10. MT【241】红蓝两色染色

    用红蓝两色给$3*3$的格子染色,要求每行每列每种颜色都有,则不同的染色方法_____ 分析:按红色格子数分类,1)红色3或者6个有6种.2)红色4或者5个有45种.故一共有2*(6+45)=102种 ...