zoukankan      html  css  js  c++  java
  • 【FFT】OpenJ_POJ

    对每个位置i处理出以其为结尾,且比a(i)大的数有j个的前缀个数,记成一个数组l;同理,处理出以其为开头,且比a(i)大的数有j个的后缀的个数,记成一个数组r。

    整个序列中比a(i)大的数的个数的数组就是对l和r数组卷积起来。

    于是枚举所有i,FFT,累加答案即可。

    但是,有可能有重复的元素,就将a(i)前面的和它相同的数当成比它大,后面的和它相同的数当成比他小即可。

    存疑:FFT的数组到底要开多大啊?四倍?还是只要是一个比卷积结果数组长度大的2的整数幂次就行了?我倾向于后者。求解。

    2#include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <cstring>
    #include <vector>
    using namespace std;
    #define EPS 1e-8
    const double PI = acos(-1.0);
    struct Complex{
        double real,image;
        Complex(double _real,double _image){
            real=_real;
            image=_image;
        }
        Complex(){}
    };
    Complex operator + (const Complex &c1,const Complex &c2){
        return Complex(c1.real+c2.real,c1.image+c2.image);
    }
    Complex operator - (const Complex &c1,const Complex &c2){
        return Complex(c1.real-c2.real,c1.image-c2.image);
    }
    Complex operator * (const Complex &c1,const Complex &c2){
        return Complex(c1.real*c2.real-c1.image*c2.image,c1.real*c2.image+c1.image*c2.real);
    }
    int rev(int id,int len){
        int ret=0;
        for(int i=0;(1<<i)<len;++i){
            ret<<=1;
            if(id&(1<<i)){
                ret|=1;
            }
        }
        return ret;
    }
    Complex tmp[2100];
    //µ±DFT==1ʱÊÇDFT, DFT==-1ʱÔòÊÇÄæDFT
    void IterativeFFT(Complex A[],int len, int DFT){//¶Ô³¤¶ÈΪlen(2µÄÃÝ)µÄÊý×é½øÐÐDFT±ä»»
        for(int i=0;i<len;++i){
            tmp[rev(i,len)]=A[i];
        }
        for(int i=0;i<len;++i){
            A[i]=tmp[i];
        }
        for(int s=1;(1<<s)<=len;++s){
            int m=(1<<s);
            Complex wm=Complex(cos(DFT*2*PI/m),sin(DFT*2*PI/m));
            for(int k=0;k<len;k+=m){//ÕâÒ»²ã½áµã°üº¬µÄÊý×éÔªËØ¸öÊý¶¼ÊÇ(1<<s)
                Complex w=Complex(1,0);
                for(int j=0;j<(m>>1);++j){//ÕÛ°ëÒýÀí£¬¸ù¾ÝÁ½¸ö×Ó½Úµã¼ÆË㸸½Úµã
                    Complex t=w*A[k+j+(m>>1)];
                    Complex u=A[k+j];
                    A[k+j]=u+t;
                    A[k+j+(m>>1)]=u-t;
                    w=w*wm;
                }
            }
        }
        if(DFT==-1){
            for(int i=0;i<len;++i){
                A[i].real/=len;
                A[i].image/=len;
            }
        }
    }
    Complex A[2100],B[2100];
    
    int wq,qw,a[2100],ans[2100][2100],l[2100],r[2100],now,i,j,k,n,m,x;
    int read()
    {
        char c;
        int ans=0;
        c=getchar();
        while (c<'0' || c>'9') c=getchar();
        while (c>='0' && c<='9') ans=ans*10+c-48,c=getchar();
        return ans;
    }
    int main()
    {
        wq=read();
        for (qw=1;qw<=wq;qw++)
        {
            n=read(); m=read();
            for (i=1;i<=n;i++) a[i]=read();
            memset(ans,0,sizeof(ans));
            for (i=1;i<=n;i++)
            {
                memset(l,0,sizeof(l)); l[0]=1;
                memset(r,0,sizeof(r)); r[0]=1;
                now=0;
                for (j=i-1;j>=1;j--)
                {
                    if (a[j]>=a[i]) now++;
                    l[now]++;
                }
                int len1=now+1;
                now=0;
                for (j=i+1;j<=n;j++)
                {
                    if (a[j]>a[i]) now++;
                    r[now]++;
                }
                int len2=now+1;
    			memset(A,0,sizeof(A));
    			memset(B,0,sizeof(B));
                for(int j=0;j<len1;++j){
                	A[j]=Complex(l[j],0);
                }
    			for(int j=0;j<len2;++j){
    				B[j]=Complex(r[j],0);
    			}
    			int len;
    			for(int j=0;;++j){
                	if((1<<j)>=len1+len2){
                    	len=(1<<j);
                    	break;
                	}
            	}
                IterativeFFT(A,len,1);
            	IterativeFFT(B,len,1);
    			for(int j=0;j<len;++j){
    				A[j]=A[j]*B[j];
    			}
            	IterativeFFT(A,len,-1);
    			for(int j=0;j<len;++j){
                	ans[a[i]][j]+=(int)(A[j].real+0.5);
           	 	}
            }
            for (i=1;i<=m;i++)
            {
                k=read(); x=read();
                printf("%d
    ",ans[x][k-1]);
            }
        }
    }
  • 相关阅读:
    java嵌套循环练习
    java菜鸡循环练习
    Kruskal重构树
    狄利克雷卷积
    莫比乌斯反演
    两道趣题
    树状数组
    多重背包
    SPFA与差分约束
    快速线性筛
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7203414.html
Copyright © 2011-2022 走看看