3509: [CodeChef] COUNTARI

题意:统计满足\(i<j<k, 2*a[j] = a[i] + a[k]\)的个数


\(2*a[j]\)不太好处理,暴力fft不如直接暴力

考虑分块

每个块用生成函数统计j在块中ik在两边的块中的

有两个在块中或者三个都在暴力统计,实时维护两边权值出现次数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int N = (1<<16) + 5, M = 1e5+5;
const double PI = acos(-1.0);
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} struct meow{
double x, y;
meow(double a=0, double b=0):x(a), y(b){}
};
meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
meow conj(meow a) {return meow(a.x, -a.y);}
typedef meow cd; namespace fft {
int n, rev[N];
cd omega[N], omegaInv[N];
void init(int lim) {
n = 1; while(n < lim) n <<= 1;
for(int i=0; i<n; i++) {
omega[i] = cd(cos(2*PI/n*i), sin(2*PI/n*i));
omegaInv[i] = conj(omega[i]);
}
}
void dft(cd *a, int n, int flag) {
cd *w = flag == 1 ? omega : omegaInv;
int k = 0; while((1<<k) < n) k++;
for(int i=0; i<n; i++) {
rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
if(i < rev[i]) swap(a[i], a[rev[i]]);
}
for(int l=2; l<=n; l<<=1) {
int m = l>>1;
for(cd *p = a; p != a+n; p += l)
for(int k=0; k<m; k++) {
cd t = w[n/l*k] * p[k+m];
p[k+m] = p[k] - t;
p[k] = p[k] + t;
}
}
if(flag == -1) for(int i=0; i<n; i++) a[i].x /= n;
}
void mul(cd *a, cd *b) {
dft(a, n, 1); dft(b, n, 1);
for(int i=0; i<n; i++) a[i] = a[i] * b[i];
dft(a, n, -1);
}
} int n, a[M], c1[N], c2[N], block, m;
cd p[N], q[N];
ll ans;
int main() {
freopen("in", "r", stdin);
n=read();
block = min(n, 8 * (int) sqrt(n));
for(int i=1; i<=n; i++) a[i] = read(), c2[a[i]]++, m = max(m, a[i]);
fft::init(m+m+1);
for(int l=1; l<=n; l+=block) {
int r = min(n, l+block-1);
for(int i=l; i<=r; i++) c2[a[i]]--;
for(int i=l; i<=r; i++) {
for(int j=i+1; j<=r; j++) {
int t = (a[j]<<1) - a[i];
if(t >= 0) ans += c2[t];
t = (a[i]<<1) - a[j];
if(t >= 0) ans += c1[t];
}
c1[a[i]]++;
}
//printf("hi [%d, %d] %lld\n", l, r, ans);
}
for(int l=1; l<=n; l+=block) { //printf("l %d\n", l);
int r = min(n, l+block-1);
memset(p, 0, sizeof(p)); memset(q, 0, sizeof(q));
for(int i=1; i<l; i++) p[a[i]].x ++;
for(int i=r+1; i<=n; i++) q[a[i]].x ++;
fft::mul(p, q);
for(int i=l; i<=r; i++) ans += (ll) floor(p[a[i]<<1].x + 0.5);
}
printf("%lld", ans);
//printf("\n%lf", (double) clock() / CLOCKS_PER_SEC);
}

bzoj 3509: [CodeChef] COUNTARI] [分块 生成函数]的更多相关文章

  1. BZOJ 3509 [CodeChef] COUNTARI ——分块 FFT

    分块大法好. 块内暴力,块外FFT. 弃疗了,抄SX队长$silvernebula$的代码 #include <map> #include <cmath> #include & ...

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

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

  3. BZOJ 3509: [CodeChef] COUNTARI

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

  4. BZOJ3509: [CodeChef] COUNTARI

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

  5. CC countari & 分块+FFT

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

  6. BZOJ3509 [CodeChef] COUNTARI 【分块 + fft】

    题目链接 BZOJ3509 题解 化一下式子,就是 \[2A[j] = A[i] + A[k]\] 所以我们对一个位置两边的数构成的生成函数相乘即可 但是由于这样做是\(O(n^2logn)\)的,我 ...

  7. CodeChef COUNTARI Arithmetic Progressions(分块 + FFT)

    题目 Source http://vjudge.net/problem/142058 Description Given N integers A1, A2, …. AN, Dexter wants ...

  8. CodeChef - COUNTARI FTT+分块

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

  9. BZOJ 3509 分块FFT

    思路: 跟今年WC的题几乎一样 (但是这道题有重 不能用bitset水过去) 正解:分块FFT http://blog.csdn.net/geotcbrl/article/details/506364 ...

随机推荐

  1. ubantu下su命令Authentication failure失败的解决方式

    Ubuntu安装后,root用户默认是被锁定了的,不允许登录,也不允许 su 到 root . 可以使用: sudo passwd 来重新设置root密码,后即可登陆root. ortonwu@ubu ...

  2. JS中使用正则表达式替换对象里的大小写

      function parse(obj){ var str = JSON.stringify(obj); var dataObj = str.replace(/Name/g, "name& ...

  3. 使用 Gacutil.exe 将.Net程序集添加到GAC的方法

    使用gacutil.exe工具安装:gacutil -i "要注册的dll文件全路径" "gacutil.exe”工具为.NET自带工具 ,需要注意的是:这个工具在.NE ...

  4. Java入门篇(六)——类和对象

    写到这里终于写到了入门篇的最后一个知识点了.类和对象是Java中经常被提到的两个词汇,实际上可以将类看作对象的载体,它定义了对象所具有的功能.Java是面向对象的语言,因此掌握类与对象是学习Java语 ...

  5. python原始字符串

    str1='let's go' File "<input>", line 1 str1='let's go' ^ SyntaxError: invalid syntax ...

  6. jQuery:图片自动变换

    <script type="text/javascript"> var aa=0; //设置变换时间为2s var timeChange=2000; //定义数组 va ...

  7. 局域网内一台电脑的ip地址自己会变,怎样让它不变

    有两种方法可以让局域网内的电脑拥有固定的ip地址: 方法一:使用DHCP的静态地址分配功能(以TP-Link TL-WR847路由器为例). 打开浏览器,输入路由器LAN口的ip地址和管理员用户名.密 ...

  8. Ajax beforeSend和complete 方法

    http://blog.csdn.net/chenjianandiyi/article/details/52274591 .ajax({ beforeSend: function(){ // Hand ...

  9. putty怎么用?如何使用Putty远程管理Linux主机

    Putty是一个免费的Windows 32平台下用于telnet.rlogin和ssh客户端的远程客户端工具,可以通过PUTTY快速的实现SSH连接linux等主机,下面小编就给大家演示一下如何使用P ...

  10. java学习总结之文件操作--ByteArrayOutputStream的用法

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区, 然后利用ByteArrayOutputStream和ByteArrayInputStream ...