zoukankan      html  css  js  c++  java
  • SPOJ:Triple Sums(母函数+FFT)

    You're given a sequence s of N distinct integers.
    Consider all the possible sums of three integers from the sequence at three different indicies.
    For each obtainable sum output the number of different triples of indicies that generate it.

    Constraints:

    N <= 40000, |si| <= 20000

    Input

    The first line of input contains a single integer N.
    Each of the next N lines contain an element of s.

    Output

    Print the solution for each possible sum in the following format:
    sum_value : number_of_triples

    Smaller sum values should be printed first.

    Example

    Input:

    5
    -1
    2
    3
    0
    5
    Output:
    1 : 1
    2 : 1
    4 : 2
    5 : 1
    6 : 1
    7 : 2
    8 : 1
    10 : 1

    Explanation:
    4 can be obtained using triples ( 0, 1, 2 ) and ( 0, 3, 4 ).
    7 can be obtained using triples ( 0, 2, 4 ) and ( 1, 3, 4 ).

    Note: a triple is considered the same as any of its permutations.

    2018/4/4,因为前几天一直在做LCT,然后基础题都长得差不多,难一点的现在还没有相同,然后搞得有些烦躁。就干脆转移下注意力。

    于是学习了下FFT,算是以为数学大渣又跨越了一小步。

    -------------------------------------分界线-----------------------------------------------

    这题可以先用母函数表示出选一个的方案(系数是物品出现次数,指数是物品价值)
    
    A(x)=a*x^1+b*x^2+c*x^3
    
    所以不考虑重复,在物品中选出三个的方案就是 1/6*A(x)^3
    现在用 B(x),C(x) 分别表示一种物品选了 2 次和 3 次的方案
    
    B(x)=a*x^2+b*x^4+c*x^6  C(x)=a*x^3+b*x^6+c*x^9

    选三个有可能是 AAB, ABA, BAA, AAA 这几种重复情况,所以扣掉后方案就是 [A(x)^3−3*A(x)⋅B(x)+2*C(x)]/6
    由于这里用到了多项式乘法,用FFT优化即可

    由于x的范围可能为负,所以假设每个数都加20000,使之变为正,最后再减去即可。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    const int maxn=1<<17;
    const double pi=acos(-1.0);
    using namespace std;
    struct complex{
        double r,i;
        complex(){};
        complex(double rr,double ii):r(rr),i(ii){}
        complex friend operator +(complex a,complex b){return (complex){a.r+b.r,a.i+b.i};}
        complex friend operator -(complex a,complex b){return (complex){a.r-b.r,a.i-b.i};}
        complex friend operator *(complex a,complex b){return (complex){a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r};}
    }tmp[maxn];
    struct DFT{
        complex a[maxn];
        void fft(int sz,int bg,int step,int opt){
           if(sz==1) return;  int m=sz>>1;
           fft(m,bg,step<<1,opt); fft(m,bg+step,step<<1,opt);
           complex w=complex(1,0),t=complex(cos(2.0*pi/sz),sin(2.0*pi*opt/sz)); 
           for(int k=0;k<m;k++)
           {
                int pos=2*step*k;
              tmp[k]=a[pos+bg]+w*a[pos+bg+step];
              tmp[k+m]=a[pos+bg]-w*a[pos+bg+step];
              w=w*t;
           }
           for(int i=0;i!=sz;i++) a[i*step+bg]=tmp[i];
        }
    }A,B,C;
    int a[maxn],b[maxn],c[maxn];
    int main(){
        int n; scanf("%d",&n);
        for(int i=0,x;i<n;i++) scanf("%d",&x),a[x+20000]++,b[2*(x+20000)]++,c[3*(x+20000)]++;
        for(int i=0;i<maxn;i++) A.a[i].r=a[i], B.a[i].r=b[i], C.a[i].r=c[i];
        A.fft(maxn,0,1,1), B.fft(maxn,0,1,1);
        for(int i=0;i<maxn;i++) C.a[i]=A.a[i]*(A.a[i]*A.a[i]-(complex){3.0,0.0}*B.a[i]);
        C.fft(maxn,0,1,-1);
        for(int i=0;i<maxn;i++){
            ll ans=((ll)(C.a[i].r/maxn+0.5)+2*c[i])/6;
            if (ans) printf("%d : %I64d
    ",i-60000,ans);
        }
        return 0;
        return 0;
    }
  • 相关阅读:
    广播系统android安全:flag FLAG_RECEIVER_REGISTERED_ONLY的意义
    产品类大话设计模式——简单工厂模式
    打印数组算法:堆栈与深度优先搜索(迷宫问题)
    函数声明第四章利用函数实现指定的功能
    构造函数调用C++ 类和动态内存分配
    命令密码MySQL忘记密码恢复密码的实现方法
    线程资源PHP源码分析之线程安全模型
    编译类【COCOS2DXLUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!
    语句数据库ubuntu下mysql的常用命令
    eclipse中配置tomcat
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8719287.html
Copyright © 2011-2022 走看看