bzoj 4927: 第一题

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4927: 第一题相关的知识,希望对你有一定的参考价值。

Description

给定n根直的木棍,要从中选出6根木棍,满足:能用这6根木棍拼
出一个正方形。注意木棍不能弯折。问方案数。
正方形:四条边都相等、四个角都是直角的四边形。

Input

第一行一个整数n。
第二行包含n个整数ai,代表每根木棍的长度。
n ≤ 5000, 1 ≤ ai ≤ 10^7

Output

一行一个整数,代表方案数。
考虑正方形每条边由几条木棍组成,只有1122和1113两种情况,分别枚举统计一下
#include<bits/stdc++.h>
typedef long long i64;
int n,a[5007],ap=0,as[5007],at[5007],t[10000007];
i64 ans=0,c3[5007];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",a+i);
    std::sort(a+1,a+n+1);
    for(int i=1,j=1;i<=n;i=j){
        int x=a[i];
        for(;j<=n&&a[j]==x;++j);
        c3[ap]=i64(j-i)*(j-i-1)*(j-i-2)/6;
        as[ap]=x;
        at[ap++]=j-i;
    }
    for(int i=1;i<=n;++i){
        for(int j=0;j<ap;++j)if(as[j]>a[i]){
            ans+=c3[j]*t[as[j]-a[i]];
        }
        for(int j=1;j<i&&a[i]+a[j]<=10000000;++j)++t[a[i]+a[j]];
    }
    for(int i=0,l,r;i<ap;++i)if(at[i]>=2){
        i64 s=0,s0=0,s1;
        for(r=i-1,l=0;r>=l;--r){
            for(;r>=l&&as[l]+as[r]<as[i];++l);
            if(r<l||as[l]+as[r]!=as[i])continue;
            int x=at[l];
            if(r==l){
                s1=x*(x-1)/2;
                s+=s1*(x-2)*(x-3)/12;
            }else{
                int y=at[r];
                s1=x*y;
                s+=s1*(x-1)*(y-1)/4;
            }
            s+=s0*s1;
            s0+=s1;
        }
        ans+=at[i]*(at[i]-1)/2*s;
    }
    printf("%lld\n",ans);
    return 0;
}

 

以上是关于bzoj 4927: 第一题的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4927第一题 双指针+DP

bzoj4980: 第一题

bzoj 1010 [HNOI2008] 玩具装箱toy (斜率优化第一题)

CodeVS 4927-线段树练习5

考后反思(bzoj3940 bzoj4899 bzoj3307)

20151105noip膜你赛bzoj3652 bzoj3653