Trap HDU

题意:

给你n个边长ai,你需要挑出来4个边使得它们可以构成等腰梯形。问你能构成多少种不同的等腰梯形

题解:

我们首先处理一下边长为x的且这个边长出现大于等于2次的边,因为等腰梯形需要两条相等的边

然后枚举上底a,和下底b,这个时候取得gcd(a,b),然后找和gcd(a,b)互质的边,且这个边要出现大于等于两次

因为等腰梯形有(上底+2*腰长)>下底,所以腰长>(下底-上底)/2

具体见代码

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int> a,b,g[maxn];
int num[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        int x;
        cin>>x;
        num[x]++;
        a.push_back(x);
    }
    sort(a.begin(),a.end());
    a.erase(unique(a.begin(),a.end()),a.end());   //去重
    int len=a.size();
//    for(int i=0;i<len;++i)
//    {
//        printf("%d ",a[i]);
//    }
//    printf("*******
");
    for(int i=0; i<=10000; i++)
    {
        if(num[i]>=2)
            b.push_back(i);
    }
    for(int i=1; i<=10000; i++)
    {
        for(int j=0; j<(int)b.size(); j++)
        {
            if(__gcd(i,b[j])==1)
                g[i].push_back(b[j]);
        }
    }
    ll ans=0;
    for(int i=0; i<a.size(); i++)
    {
        for(int j=i+1; j<a.size(); j++)
        {
            int limit = (a[j]-a[i])%2==0?(a[j]-a[i])/2+1:(a[j]-a[i]+1)/2;  //等腰梯形限制条件
            int d = __gcd(a[i],a[j]);
            int index = lower_bound(g[d].begin(),g[d].end(),limit)-g[d].begin();
            ans=ans+g[d].size()-index;
            if(d==1)  //特判一下等腰梯形三条边都相等的情况
            {
                if(num[a[i]]==2&&a[i]>=limit)ans--;
                if(num[a[j]]==2&&a[j]>=limit)ans--;
            }
        }
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13833637.html