• (FFT)A+B Problem


     题目链接:https://cn.vjudge.net/contest/280041#problem/B

    题目大意:给你n个数,然后让你找满足a[i] + a[j] = a[k] 的情况总数。

    具体思路:首先把每一种情况的个数算出来(两个数相加的结果),然后再就是去重的过程。

    (因为题目中会有负数,我们可以全部转换成非负数去进行计算)

    1,自己和自己相加。

    2,1+0=1,0+1=1这个时候,1是使用了两次,所以需要去掉这种情况,就是去掉(0的总数)*2.

    3,0+0=0,0+0=0,这个时候我们可以按照第一种的思路来(这个时候i!=j,因为自己加自己情况已经去掉了),把其中一个0看成(非0的数),然后再按照公式进行计算,不过计算的时候是(0的总数-1)*2.

    AC代码:

      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<stdio.h>
      7 using namespace std;
      8 # define ll long long
      9 const double PI = acos(-1.0);
     10 const int maxn = 2e5+100;
     11 struct complex
     12 {
     13     double r,i;
     14     complex(double _r = 0,double _i = 0)
     15     {
     16         r = _r;
     17         i = _i;
     18     }
     19     complex operator +(const complex &b)
     20     {
     21         return complex(r+b.r,i+b.i);
     22     }
     23     complex operator -(const complex &b)
     24     {
     25         return complex(r-b.r,i-b.i);
     26     }
     27     complex operator *(const complex &b)
     28     {
     29         return complex(r*b.r-i*b.i,r*b.i+i*b.r);
     30     }
     31 };
     32 void change(complex y[],int len)
     33 {
     34     int i,j,k;
     35     for(i = 1, j = len/2; i < len-1; i++)
     36     {
     37         if(i < j)
     38             swap(y[i],y[j]);
     39         k = len/2;
     40         while( j >= k)
     41         {
     42             j -= k;
     43             k /= 2;
     44         }
     45         if(j < k)
     46             j += k;
     47     }
     48 }
     49 void fft(complex y[],int len,int on)
     50 {
     51     change(y,len);
     52     for(int h = 2; h <= len; h <<= 1)
     53     {
     54         complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
     55         for(int j = 0; j < len; j += h)
     56         {
     57             complex w(1,0);
     58             for(int k = j; k < j+h/2; k++)
     59             {
     60                 complex u = y[k];
     61                 complex t = w*y[k+h/2];
     62                 y[k] = u+t;
     63                 y[k+h/2] = u-t;
     64                 w = w*wn;
     65             }
     66         }
     67     }
     68     if(on == -1)
     69         for(int i = 0; i < len; i++)
     70             y[i].r /= len;
     71 }
     72 const int T=5e4;
     73 complex x1[maxn<<1];
     74 ll num[maxn<<1],a[maxn<<1],b[maxn<<1];
     75 int main()
     76 {
     77     int n;
     78     scanf("%d",&n);
     79     int ans=0;
     80     int len=1;
     81     while(len<maxn)
     82         len<<=1;
     83     for(int i=0; i<n; i++)
     84     {
     85         scanf("%lld",&a[i]);
     86         if(a[i]==0)
     87             ans++;
     88         b[a[i]+T]++;
     89     }
     90     for(int i=0; i<len; i++)
     91     {
     92         x1[i]=complex(b[i],0);
     93     }
     94     fft(x1,len,1);
     95     for(int i=0; i<len; i++)
     96     {
     97         x1[i]=x1[i]*x1[i];
     98     }
     99     fft(x1,len,-1);
    100     for(int i=0; i<len; i++)
    101     {
    102         num[i]=(ll)(x1[i].r+0.5);
    103     }
    104     for(int i=0; i<n; i++)
    105     {
    106         num[(a[i]+T)*2]--;
    107     }//重复的去掉
    108     ll sum=0;
    109  //   cout<<num[T+T]<<endl;
    110     for(int i=0; i<n; i++)
    111     {
    112         sum+=num[a[i]+2*T];//比如说 1 2 3 ,我们现在要计算能组成3的个数,也就是3加上 2 个T,因为他的两个因子分别有一个T
    113         sum-=(ans-(a[i]==0))*2;// 0+4 =4 ,4+0=4,这个时候4是用了两遍的,所以减去的就应该是ans*2。
    114        // 对于0+0等于0,这种情况,如果说当前只有两个0的话,num[0]是等于2的(去重之后),这个时候我们就把其中一个0看成非0的,然后再按照上面的步骤进行计算。
    115     }
    116     printf("%lld
    ",sum);
    117     return 0;
    118 }
  • 相关阅读:
    【计蒜客】贝壳找房户外拓展(中等)扫描线+线段树
    【CodeForces】925 C.Big Secret 异或
    【LibreOJ】#6392. 「THUPC2018」密码学第三次小作业 / Rsa 扩展欧几里得算法
    【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序
    【BZOJ】1095: [ZJOI2007]Hide 捉迷藏 括号序列+线段树
    【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas
    【计蒜客】百度科学家(困难)
    【BZOJ】2115: [Wc2011] Xor
    【GDOI2018】所有题目和解题报告
    【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10302709.html
Copyright © 2020-2023  润新知