zoukankan      html  css  js  c++  java
  • 【BZOJ4927】第一题 双指针+DP

    题解:

    虽然是过了,不过做的十分智障

    首先是有 2根 2 1 1 , 3根 1 1 1

    这两种方法

    然后考虑2 2 1 1

    two-point-two没啥好说的

    3 1 1 1

    我很智障的以为数据范围是1e9

    然后写了hash,刚开始还开错范围

    把int换short int才卡过了空间

    首先枚举 1 1 1

    然后枚举3 中的一条边

    既然1e7直接记录每个数能由两个数组成的方案数

    另外再减去这条边参与的方案数(直接两个数减一下查有几个就好了)

    然后细节还挺多的搞个对拍就可以了

    #pragma G++ optimize (2)
    #include <bits/stdc++.h>
    using namespace std;
    #define N 6000
    #define rg register
    #define IL inline
    #define ll long long
    int a[N],n;
    unsigned ll ans,ans3;
    #define js(x) x*(x-1)/2*(x-2)/3*(x-3)/4
    const int mo1=1.3e7+7;
    const int NN=1.3e7+1e5;
    const int mo2=2.6e7+7;
    const int N2=2.6e7+1e5;
    int hash1[NN],hash2[NN],hash4[N2];
    short int hash3[N2],hash5[N2];
    char ss[1<<20],*A=ss,*B=ss;
    inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<20,stdin),A==B)?EOF:*A++;}
    template<class T>void read(T&x){
        rg int f=1,c;while(c=gc(),c<48||57<c)if(c=='-')f=-1;x=c^48;
        while(c=gc(),47<c&&c<58)x=(x<<3)+(x<<1)+(c^48);x*=f;
    }
    IL void push(int x)
    {
      int y=x%mo1;
      while (hash1[y]&&hash1[y]!=x) y++;
      hash1[y]=x; hash2[y]++;
    }
    IL int find1(int x)
    {
      int y=x%mo1;
      while (hash1[y]&&hash1[y]!=x) y++;
      if (hash1[y]==x) return(hash2[y]);
      else return(0);
    }
    IL void push2(int x,int y)
    {
      int z=(1ll*y*5000+x)%mo2;
      while (hash3[z]&&!(hash3[z]==x&&hash4[z]==y)) z++;
      hash3[z]=x; hash4[z]=y; hash5[z]++;
    }
    IL int find2(int x,int y)
    {
      int z=(1ll*y*5000+x)%mo2;
      while (hash3[z]&&!(hash3[z]==x&&hash4[z]==y)) z++;
      if (hash3[z]==x&&hash4[z]==y) return(hash5[z]);
      else return(0);
    }
    IL bool cmp(int a,int b)
    {
      return(a<b);
    }
    int now,cnt;
    #define INF 1e9
    int main()
    {
      freopen("noi.in","r",stdin);
      freopen("noi.out","w",stdout);
      read(n);
      for (rg int i=1;i<=n;i++) read(a[i]);
      sort(a+1,a+n+1,cmp);
      for (rg int i=1;i<=n;i++)
        for (rg int j=i+1;j<=n;j++)
          push(a[i]+a[j]);
      a[0]=INF;
      for (rg int i=1;i<=n;i++)
          for (rg int j=i+1;j<=n;j++)
              push2(i,a[i]+a[j]),push2(j,a[i]+a[j]);
      now=0;
      while (++now<=n)
      {
        cnt=1;
        while (now<n&&a[now+1]==a[now]) cnt++,now++;
        if (cnt>=2)
        {
          int h=1,t=n;
          ll ans2=0;
          while (h<t)
          {
            int h1=h,t1=t;
            while (a[h]==a[h+1]&&h<t) h++;
            while (a[t]+a[h]>a[now]&&h<t) t--;
            if (a[t]+a[h]!=a[now])
            { 
              h++;
              continue;
            }
            t1=t;
            while (a[t]==a[t-1]&&h<t) t--;
            if (h==t)
            {
              int xx=t1-h1+1;
              if (t1-h1+1>=4) ans+=1ll*cnt*(cnt-1)/2*js(xx);
              ans+=1ll*ans2*cnt*(cnt-1)/2*(t1-h1+1)*(t1-h1)/2;
              break;
            }
            if (h-h1>=1&&t1-t>=1)
            {
              ans+=1ll*cnt*(cnt-1)/2*(h-h1)*(h-h1+1)/2*(t1-t)*(t1-t+1)/2;
            }
            ans+=1ll*cnt*(cnt-1)/2*ans2*(t1-t+1)*(h-h1+1);
            ans2+=(t1-t+1)*(h-h1+1);
            h++;
          } 
        }
        if (cnt>=3)
        {
          rg ll ans2=1ll*cnt*(cnt-1)*(cnt-2)/6;
          unsigned rg ll ans4=0;
          for (rg int i=1;i<=n;i++)
          {
            if (a[now]>a[i])
            {
              int x=find1(a[now]-a[i]);
              int y=find2(i,a[now]-a[i]);
              ans4+=1ll*(x-y)*ans2;
            }
          }
          ans3+=ans4/3;
        } 
      }
      //ans3/=3;
      cout<<ans+ans3<<endl;
      return 0;
    }

    对拍 n^6

    #include <bits/stdc++.h>
    using namespace std;
    #define rg register
    #define N 10000
    #define rep(i,x,y) for (rg int i=x;i<=y;i++)
    int b[10];
    bool cmp(int x,int y)
    {
      return(x<y);
    }
    int a[N],n;
    bool pd1(int x1,int x2,int x3,int x4,int x5,int x6)
    {
      b[1]=a[x1],b[2]=a[x2],b[3]=a[x3],b[4]=a[x4],b[5]=a[x5],b[6]=a[x6];
      sort(b+1,b+6+1,cmp);
      if (b[1]+b[4]==b[2]+b[3]&&b[2]+b[3]==b[5]&&b[5]==b[6])
        return(1); else return(0);
    }
    bool pd2(int x1,int x2,int x3,int x4,int x5,int x6)
    {
        b[1]=a[x1],b[2]=a[x2],b[3]=a[x3],b[4]=a[x4],b[5]=a[x5],b[6]=a[x6];
      sort(b+1,b+6+1,cmp);
      if (b[1]+b[2]+b[3]==b[4]&&b[4]==b[5]&&b[5]==b[6])
        return(1); else return(0);
    }
    int main()
    {
      freopen("noi.in","r",stdin);
      freopen("noi2.out","w",stdout);
      std::ios::sync_with_stdio(false);
      cin>>n;
      for (int i=1;i<=n;i++) cin>>a[i];
      int cnt=0,cnt2=0;
      rep(i1,1,n)
        rep(i2,i1+1,n)
          rep(i3,i2+1,n)
            rep(i4,i3+1,n)
              rep(i5,i4+1,n)
                rep(i6,i5+1,n)
                  if (pd1(i1,i2,i3,i4,i5,i6))
                  {
                   
                    cnt++;
                  }
      rep(i1,1,n)
        rep(i2,i1+1,n)
          rep(i3,i2+1,n)
            rep(i4,i3+1,n)
              rep(i5,i4+1,n)
                rep(i6,i5+1,n)
                  if (pd2(i1,i2,i3,i4,i5,i6))
                 {
              //      cout<<i1<<" "<<i2<<" "<<i3<<" "<<i4<<" "<<i5<<" "<<i6<<endl;
                    cnt++;
                  }
      cout<<cnt+cnt2<<endl;
      return 0;
    }
  • 相关阅读:
    滑雪(dp好题)
    田忌赛马
    反质数(Antiprimes)
    LCA-倍增法(在线)
    二模 (2) day2
    Spring Integration
    [转载] Spring MVC
    收藏夹
    Linux profile File
    git merge 与 rebase 的区别
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8975819.html
Copyright © 2011-2022 走看看