[Codechef November Challenge 2012] Arithmetic Progressions

题意:给定一个序列,求多少个三元组满足ai+ak=2*aj(i<j<k)。

题解:原来叉姐的讲义上有啊。。完全忘掉了。。

首先这个式子很明显是一个卷积。我们有了FFT的思路。但是肯定不能每一个数都去做一次。那怎么办呢?我们分块吧!(分块大法好)

对于每一个块我们统计出前面块的桶,同理我们也有后面块的桶,两个桶FFT一下我们就得到了以这个块内元素为j,i和k分别在前面的块与后面的块的方案了。然后我们还要解决两个在一个块,三个在一个块的问题。两个在一个块的我们直接去前后的桶里找,同一个块的直接n*n暴力。然后就做完啦!好妙啊!

这题被坑了好久。。因为空间莫名其妙的问题怎么都算不对(块开极端都可以,就是开中间不行),然后一个下午没有了。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define N 205005
 5 #define INF 1e9
 6 #define Bl 70
 7 #define LIM 60000
 8 const double PI=acos(-1);
 9
10 inline LL read(){
11        LL x=0,f=1; char a=getchar();
12        while(a<‘0‘ || a>‘9‘) {if(a==‘-‘) f=-1; a=getchar();}
13        while(a>=‘0‘ && a<=‘9‘) x=x*10+a-‘0‘,a=getchar();
14        return x*f;
15 }
16
17 namespace FFT{
18     int rev[N];
19
20     struct vec{
21         double r,i;
22         vec operator * (const vec& w){return (vec){r*w.r-i*w.i,i*w.r+r*w.i};}
23         vec operator + (const vec& w){return (vec){r+w.r,i+w.i};}
24         vec operator - (const vec& w){return (vec){r-w.r,i-w.i};}
25     }A[N],B[N];
26
27     inline void fft(vec* x,int len,int f){
28         for(int i=1;i<=len;i++) if(i<rev[i]) swap(x[i],x[rev[i]]);
29         for(int lnow=2;lnow<=len;lnow<<=1){
30             vec w,w0=(vec){cos(2.0*PI/lnow*f),sin(2.0*PI/lnow*f)},t1,t2;
31             for(int i=0;i<len;i+=lnow){
32                 w=(vec){1,0};
33                 for(int j=i;j<i+lnow/2;j++){
34                     t1=x[j]; t2=w*x[j+lnow/2];
35                     x[j]=t1+t2; x[j+lnow/2]=t1-t2;
36                     w=w*w0;
37                 }
38             }
39         }
40     }
41
42     inline void work(int a[],int b[],int l1,int l2,LL s[]){
43         int len,t;
44         for(len=1,t=0;len<=(l1+l2+1);len<<=1,t++); t=1<<(t-1);
45         for(int i=0;i<=len;i++) rev[i]=rev[i>>1]>>1|(i&1?t:0);
46         for(int i=0;i<=len;i++) B[i]=A[i]=(vec){0,0};
47         for(int i=0;i<=l1;i++) A[i].r=a[i];
48         for(int i=0;i<=l2;i++) B[i].r=b[i];
49         fft(A,len,1); fft(B,len,1);
50         for(int i=0;i<=len;i++) A[i]=A[i]*B[i];
51         fft(A,len,-1);
52         for(int i=0;i<=l1+l2;i++)
53         s[i]=(LL)(1.0*A[i].r/len+0.5);
54     }
55
56 }
57
58 int n,block_size,block_num;
59 int bel[N],l[Bl+5],r[Bl+5],a[N];
60 LL tot,ans[2*LIM+6000];
61 int lsum[LIM+5],rsum[LIM+5],cnt[2*LIM+5];
62
63 inline void brutal_force(int x){
64     for(int i=l[x];i<=r[x];i++) rsum[a[i]]--;
65     memset(ans,0,sizeof(ans));
66     FFT::work(lsum,rsum,30000,30000,ans);
67     for(int i=l[x];i<=r[x];i++){
68         tot+=ans[2*a[i]];
69         for(int j=l[x];j<i;j++)
70         if(2*a[i]-a[j]>0) tot+=rsum[2*a[i]-a[j]];
71         for(int j=i+1;j<=r[x];j++)
72         if(2*a[i]-a[j]>0) tot+=lsum[2*a[i]-a[j]];
73     }
74     for(int i=l[x];i<=r[x];i++) lsum[a[i]]++;
75     memset(cnt,0,sizeof(cnt));
76     for(int i=l[x];i<=r[x];i++){
77         tot+=cnt[a[i]];
78         for(int j=l[x];j<i;j++)
79         if(2*a[i]-a[j]>0) cnt[2*a[i]-a[j]]++;
80     }
81 }
82
83 int main(){
84     n=read(); block_size=1500;
85     block_num=(n-1)/block_size+1;
86     for(int i=1;i<=n;i++) a[i]=read(),bel[i]=(i-1)/block_size+1;
87     for(int i=1;i<=block_num;i++) l[i]=(i-1)*block_size+1,r[i]=min(n,i*block_size);
88     for(int i=1;i<=n;i++) rsum[a[i]]++;
89     for(int i=1;i<=block_num;i++) brutal_force(i);
90     printf("%lld\n",tot);
91     return 0;
92 }
时间: 2024-09-29 09:01:16

[Codechef November Challenge 2012] Arithmetic Progressions的相关文章

CodeChef November Challenge 2014

重点回忆下我觉得比较有意义的题目吧.水题就只贴代码了. Distinct Characters Subsequence 水. 代码: 1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cmath> 7 #include <algorithm> 8 #

poj 3006 Dirichlet&#39;s Theorem on Arithmetic Progressions

Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a + 4d, ..., contains infinitely many prime numbers. This fact is known as Dirichlet's Theore

Codechef July Challenge 2014部分题解

Dish Owner(并查集) 链接:http://www.codechef.com/JULY14/problems/DISHOWN/ 题意分析:本题主要操作就是给出0 x y时,拥有第x道菜的厨师与拥有第y道菜的厨师pk,谁拥有的所有菜的其中一道菜(不一定是x或y)的分值比较高谁就获胜,并赢得loser的所有菜.即比较的是每个人分值最高的菜,所以对于非loser的人来说,他的分值最高的菜是不变的.综合题意用并查集易解. #include <cstdio> const int Maxn=100

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

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a 

POJ 3006 Dirichlet&#39;s Theorem on Arithmetic Progressions 素数 难度:0

http://poj.org/problem?id=3006 #include <cstdio> using namespace std; bool pm[1000002]; bool usd[1000002]; bool judge(int x) { if(usd[x])return pm[x]; usd[x] = true; if(x == 2) return pm[x] = true; if(((x & 1) == 0) || (x < 2))return pm[x] =

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

P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题解 最新讨论• 这道题有问题• 怎么进一步优化时间效率啊 …题目描述一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列.在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平

USACO 1.4 Arithmetic Progressions

Arithmetic Progressions An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb where n=0,1,2,3,... . For this problem, a is a non-negative integer and b is a positive integer. Write a program that finds all arithmetic progression

poj3006 Dirichlet&#39;s Theorem on Arithmetic Progressions

Dirichlet's Theorem on Arithmetic Progressions Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16333   Accepted: 8205 Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing

【POJ3006】Dirichlet&#39;s Theorem on Arithmetic Progressions(素数筛法)

简单的暴力筛法就可. 1 #include <iostream> 2 #include <cstring> 3 #include <cmath> 4 #include <cctype> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <numeric> 9 using namespace std; 10 11 co