1. 程式人生 > >【BZOJ4927】第一題 雙指針+DP

【BZOJ4927】第一題 雙指針+DP

color esp 記錄 AS ret OS har emp #define

題解:

雖然是過了,不過做的十分智障

首先是有 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;
}

【BZOJ4927】第一題 雙指針+DP