Gym100783C Golf Bot(FFT)

https://vjudge.net/problem/Gym-100783C

题意:

给出n个数,然后有m次查询,每次输入一个数x,问x能否由n个数中2个及2个以下的数相加组成。

思路:
题意很简单,但是如果直接去算要超时。

可以利用傅里叶,计算出两个卷积中的数相加的所有可能性。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<string>
  6 #include<vector>
  7 #include<queue>
  8 #include<cmath>
  9 using namespace std;
 10
 11 #define LL long long
 12 const double PI = acos(-1.0);
 13
 14 //  复数结构体
 15 struct Complex
 16 {
 17     double x, y;    //  实部和虚部 x + yi
 18     Complex(double _x = 0.0, double _y = 0.0)
 19     {
 20         x = _x;
 21         y = _y;
 22     }
 23     Complex operator - (const Complex &b) const
 24     {
 25         return Complex(x - b.x, y - b.y);
 26     }
 27     Complex operator + (const Complex &b) const
 28     {
 29         return Complex(x + b.x, y + b.y);
 30     }
 31     Complex operator * (const Complex &b) const
 32     {
 33         return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
 34     }
 35 };
 36
 37 //  进行FFT和IFFT前的反转变换
 38 //  位置i和(i二进制反转后的位置)互换
 39 //  len必须去2的幂
 40 void change(Complex y[], int len)
 41 {
 42     int i, j, k;
 43     for (i = 1, j = len / 2; i < len - 1; i++)
 44     {
 45         if (i < j)
 46         {
 47             swap(y[i], y[j]);
 48         }
 49         //  交换护卫小标反转的元素,i < j保证交换一次
 50         //  i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
 51         k = len / 2;
 52         while (j >= k)
 53         {
 54             j -= k;
 55             k /= 2;
 56         }
 57         if (j < k)
 58         {
 59             j += k;
 60         }
 61     }
 62     return ;
 63 }
 64
 65 //  FFT
 66 //  len必须为2 ^ k形式
 67 //  on == 1时是DFT,on == -1时是IDFT
 68 void fft(Complex y[], int len, int on)
 69 {
 70     change(y, len);
 71     for (int h = 2; h <= len; h <<= 1)
 72     {
 73         Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
 74         for (int j = 0; j < len; j += h)
 75         {
 76             Complex w(1, 0);
 77             for (int k = j; k < j + h / 2; k++)
 78             {
 79                 Complex u = y[k];
 80                 Complex t = w * y[k + h / 2];
 81                 y[k] = u + t;
 82                 y[k + h / 2] = u - t;
 83                 w = w * wn;
 84             }
 85         }
 86     }
 87     if (on == -1)
 88     {
 89         for (int i = 0; i < len; i++)
 90         {
 91             y[i].x /= len;
 92         }
 93     }
 94 }
 95
 96 const int maxn=200000+100;
 97
 98 Complex x1[5*maxn];
 99 int a[5*maxn];
100 LL num[5*maxn];
101
102 int main()
103 {
104     //freopen("D:\\input.txt","r",stdin);
105     int n,m;
106     while(~scanf("%d",&n))
107     {
108         memset(num,0,sizeof(num));
109         for(int i=0;i<n;i++)
110         {
111             scanf("%d",&a[i]);
112             num[a[i]]++;
113         }
114         a[n]=0; n++; num[0]++;
115         sort(a,a+n);
116         int len1=a[n-1]+1;
117         int len=1;
118         while(len<2*len1) len<<=1;
119         for(int i=0;i<len1;i++)
120             x1[i]=Complex(num[i],0);
121         for(int i=len1;i<len;i++)
122             x1[i]=Complex(0,0);
123         fft(x1,len,1);
124         for(int i=0;i<len;i++)
125             x1[i]=x1[i]*x1[i];
126         fft(x1,len,-1);
127         for(int i=0;i<len;i++)
128             num[i]=(long long)(x1[i].x+0.5);
129         len=2*a[n-1];
130         //for(int i=0;i<n;i++)//减去2次选的同一个数
131            // num[a[i]+a[i]]--;
132         //for(int i=1;i<=len;i++) num[i]/=2;//选1 2和选2 1是一样的所以除2
133
134         //for(int i=0;i<=10;i++)
135            //printf("%d: %d\n",i,num[i]);
136         int ans=0;
137         scanf("%d",&m);
138         while(m--)
139         {
140             int xx;
141             scanf("%d",&xx);
142             if(num[xx])  ans++;
143         }
144         printf("%d\n",ans);
145     }
146 }
时间: 2024-10-28 20:23:29

Gym100783C Golf Bot(FFT)的相关文章

LA6886 Golf Bot(FFT)

题目 Source https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4898 Description Do you like golf? I hate it. I hate golf so much that I decided to build the ultimate golf robot, a robot that wi

快速傅里叶变换(FFT)

快速傅里叶变换(FFT)算法[详解] 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的"对称性",并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶

Hdu 1402 (FFT)

题目链接 A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12490    Accepted Submission(s): 2206 Problem Description Calculate A * B. Input Each line will contain two integers A and

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1

BZOJ[3527],[ZJOI2014]力(FFT)

BZOJ[3527],[ZJOI2014]力(FFT) 题意: 给出\(n\)个数\(q_i\),给出\(Fj\)的定义如下: \(F_j=\sum \limits _ {i < j} \frac{q_iq_j}{(i-j)^2}-\sum \limits _{i >j} \frac{q_iq_j}{(i-j)^2}.\) 令\(E_i=F_i/q_i\),求\(E_i\). 题解: 一开始没发现求\(E_i\)... 其实题目还更容易想了... \(E_i=\sum\limits _{j&l

【知识总结】快速傅里叶变换(FFT)

这可能是我第五次学FFT了--菜哭qwq 先给出一些个人认为非常优秀的参考资料: 一小时学会快速傅里叶变换(Fast Fourier Transform) - 知乎 小学生都能看懂的FFT!!! - 胡小兔 - 博客园 快速傅里叶变换(FFT)用于计算两个\(n\)次多项式相乘,能把复杂度从朴素的\(O(n^2)\)优化到\(O(nlog_2n)\).一个常见的应用是计算大整数相乘. 本文中所有多项式默认\(x\)为变量,其他字母均为常数.所有角均为弧度制. 一.多项式的两种表示方法 我们平时常

HDU 4609 3-idiots(FFT)

题意:给出n个正整数(数组A).每次随机选出三个数.问这三个数能组成三角形的概率为多大? 首先,我们用类似桶排计数的方法作出两个数组a,b,储存每个长度有几条边,然后对两个数组求卷积. 求出卷积后,这就代表了2条边能构成的边长度的集合了,注意,由于求卷积的时候可能把两条相同的边相加,所以最后求出的数组一定要减去这重复的部分,然后,先算x后算y等价于先算y后算x,所以要除以二. 然后,对于第三条边a[i],我们这样考虑:令它作为这三条边中最大的那条! 所以之前的卷积求出来的两边和一定会比这条边大,

傅里叶变换(FFT)的多相滤波结构实现

作者:桂. 时间:2017-09-25  14:53:01 链接:http://www.cnblogs.com/xingshansi/p/7591868.html 前言 以前在梳理信号频域变换的时候,提到逆序级联FFT(Inverse cascade FFT)的实现思路,后来分析多相滤波信道化,才发现其实Cascade FFT就是FFT的多相结构实现,在此系统梳理一下. 一.多相结构FFT实现 A-传统测频技术分析 信号的短时傅里叶变换(STFT)可表示为: 其中s为输入信号,w为对应窗函数.长

【ZOJ 3856】Goldbach(FFT)

题意:最多使用三个质数做加法和乘法,问得到X有多少种方案. 这道题的话分几种情况讨论清楚就好了. 1.只有一个数的情况,如果这个数是质数则方案数加1 2.有两个数的情况,可以将两个数做加法和乘法,加法的话将质数得到的数字做一遍FFT,乘法直接做sqrt(n) * sqrt(n)就好了 3.有三个数的情况,分别有三种方法,分别是a + b + c, a + b * c,a * b * c 对于a * b * c,暴力遍历一遍就好,对于a + b * c,首先暴力遍历下b * c,然后再将一个数的两