zoukankan      html  css  js  c++  java
  • 2019 上海icpc网络赛 C FFT优化卷积+小范围暴力

    https://nanti.jisuanke.com/t/41400

    对于大的情况,我们依次对a与b,a与c,c与b的权值数组去卷积,然后答案就是$n^3$,减去卷积后不合法的情况

    但是由于值域每次都是$1e5$,且要进行6次卷积,

    单组复杂度每次都是$6*2^{ceil(log_2(2n))}ceil(log_2(2n)),n=1e5,ceil(x)$为向上取整,

    100组测试数据的情况下,可以达到$2.8e9$

    但是我们发现,只有五分之一的数据满足$n>1000$

    因此,对于小范围数据,我们直接使用$n^2$的暴力

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    using namespace std;//head
    const int maxn=4e5+10,maxm=2e6+10;
    const ll INF=0x3f3f3f3f,mod=1e9+7;
    int casn,n,m,k,kase=1,l,r;
    namespace fastio{//@支持读取整数,字符串,输出整数@
    bool isdigit(char c){return c>=48&&c<=57;}
    const int maxsz=1e7;
    class fast_iostream{public:
      char ch=get_char();
      bool endf=1,flag;
      char get_char(){
        static char buffer[maxsz],*a=buffer,*b=buffer;
        return b==a&&(b=(a=buffer)+fread(buffer,1,maxsz, stdin),b==a)?EOF:*a++;
      }
      template<typename type>bool get_int(type& tmp){
        flag=tmp=0;
        while(!isdigit(ch)&&ch!=EOF){flag=ch=='-';ch=get_char();};
        if(ch==EOF)return endf=0;
        do{tmp=ch-48+tmp*10;}while(isdigit(ch=get_char()));
        if(flag)tmp=-tmp;
        return 1;
      }
      int get_str(char* str){
        char* tmp=str;
        while(ch=='
    '||ch=='
    '||ch==' ')ch=get_char();
        if(ch==EOF)return(endf=0),*tmp=0;
        do{*(tmp++)=ch;ch=get_char();}while(ch!='
    '&&ch!='
    '&&ch!=' '&&ch!=EOF);
        *(tmp++)=0;
        return(int)(tmp-str-1);
      }
      fast_iostream& operator>>(char* tmp){get_str(tmp);return *this;}
      template<typename type>fast_iostream& operator>>(type& tmp){get_int(tmp);return *this;}
      operator bool() const {return endf;}
    };
    }fastio::fast_iostream io;
    
    const double pi=acos(-1.0);
    struct cp{double x,y;};
    cp operator*(cp a,cp b){return {a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
    cp operator+(cp a,cp b){return {a.x+b.x,a.y+b.y};}
    cp operator-(cp a,cp b){return {a.x-b.x,a.y-b.y};}
    class fourier{public:
      int rev[maxn],len,pw;
      void init(int n){
        len=1,pw=0;
        while(len<=n) len<<=1,pw++;
        rep(i,0,len-1) rev[i]=0;
        rep(i,0,len-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(pw-1));
      }
      void transform(cp*a,int flag){
        rep(i,0,len-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int mid=1;mid<len;mid<<=1){
          cp wn={cos(pi/mid),flag*sin(pi/mid)};
          for(int r=mid<<1,j=0;j<len;j+=r){
            cp t={1,0};
            for(int k=0;k<mid;k++,t=t*wn){
              cp x=a[j+k],y=t*a[mid+j+k];
              a[j+k]=x+y,a[j+k+mid]=x-y;
            }
          }
        }
        if(flag==-1) rep(i,0,len) a[i].x/=len;
      }
    }fft;
    int a[maxn],b[maxn],c[maxn];
    cp cnta[maxn],cntb[maxn],cntc[maxn];
    cp resa[maxn],resb[maxn],resc[maxn];
    ll suma[maxn],sumb[maxn],sumc[maxn];
    #define cin io
    int main(){
      cin>>casn;
      while(kase<=casn){
        cin>>n;
        fft.init(1e5+1e5+2);
        if(n<=1000){
          rep(i,1,n)cin>>a[i];
          rep(i,1,n)cin>>b[i];
          rep(i,1,n)cin>>c[i];
          ll ans=1ll*n*n*n;
          sort(c+1,c+1+n);
          sort(b+1,b+1+n);
          sort(a+1,a+1+n);
          rep(i,1,c[n]) suma[i]=0;
          rep(i,1,n)rep(j,1,n) ++suma[a[i]+b[j]];
          rep(i,1,c[n])suma[i]+=suma[i-1];
          rep(i,1,n) ans-=suma[c[i]-1];
          rep(i,1,b[n]) suma[i]=0;
          rep(i,1,n)rep(j,1,n) ++suma[a[i]+c[j]];
          rep(i,1,b[n])suma[i]+=suma[i-1];
          rep(i,1,n) ans-=suma[b[i]-1];
          rep(i,1,a[n]) suma[i]=0;
          rep(i,1,n)rep(j,1,n) ++suma[c[i]+b[j]];
          rep(i,1,a[n])suma[i]+=suma[i-1];
          rep(i,1,n) ans-=suma[a[i]-1];
          printf("Case #%d: %lld
    ",kase++,ans);
          continue; 
        }
        rep(i,1,n) {
          cin>>a[i];
          cnta[a[i]].x++;
        }
        rep(i,1,n) {
          cin>>b[i];
          cntb[b[i]].x++;
        }
        rep(i,1,n) {
          cin>>c[i];
          cntc[c[i]].x++;
        }
        fft.transform(cnta,1);fft.transform(cntb,1);fft.transform(cntc,1);
        rep(i,0,fft.len-1){
          resa[i]=cntb[i]*cntc[i];
          resb[i]=cnta[i]*cntc[i];
          resc[i]=cntb[i]*cnta[i];
        }
        fft.transform(resa,-1);fft.transform(resb,-1);fft.transform(resc,-1);
        rep(i,1,fft.len-1){
          suma[i]=suma[i-1]+(ll)(resa[i].x+0.5);
          sumb[i]=sumb[i-1]+(ll)(resb[i].x+0.5);
          sumc[i]=sumc[i-1]+(ll)(resc[i].x+0.5);
        }
        ll ans=n*1ll*n*n;
        rep(i,1,n){
          ans-=suma[a[i]-1]+sumb[b[i]-1]+sumc[c[i]-1];
        }
        printf("Case #%d: %lld
    ",kase++,ans);
        rep(i,0,fft.len){
          cnta[i]=cntb[i]=cntc[i]=(cp){0,0};
        }
      }
    }
    
  • 相关阅读:
    如何配置MySQL
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    Python 【面试总结】
    Vue【你知道吗?】
    Python 【面试强化宝典】
    Python 【基础面试题】
    Vue 【前端面试题】
    Redis 【常识与进阶】
  • 原文地址:https://www.cnblogs.com/nervendnig/p/11525240.html
Copyright © 2011-2022 走看看