2019CCPC-江西省赛C题 HDU6569 GCD预处理+二分

Trap

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 100    Accepted Submission(s): 39


Problem Description
Avin is studying isosceles trapezoids. An isosceles trapezoid is a convex quadrilateral with two opposite parallel bases, two equal-length legs and positive area. In this problem, we further require that the two legs are not parallel. Given n segments, you are asked to find the number of isosceles trapezoids whose 4 edges are from these segments and the greatest common divisor of their lengths is 1. Two congruent isosceles trapezoids are counted only once.
 
Input
The first line contains a number n (4 ≤ n ≤ 2, 000). The second line contains n numbers, each of which represents the length of a segment (the length is within [2, 10000]).
 
Output
Print the number of non-congruent isosceles trapezoids.
 
Sample Input
5
4 4 2 8 9
6
4 4 4 2 8 9
 
Sample Output
2
3
 
题意 n条线段,每条线段的长度为ai,问能够组成等腰梯形的方案数,要求四条边的gcd为1,且不是矩形,即上底下底不能相等。(4<=n<=2000,2<=ai<=10000)
解析 n只有1000 我们可以先排序去重,然后$n^2$枚举 上底 i ,下底 j,我们要找有多少个数x 满足 x的数量>=2 且 长度能与上底下底组成四边形 且 x与上底下底的gcd的gcd等于1,
所以我们预处理出来一些东西 二分去查找, 上底下底的gcd=1的时候要处理一下。
代码
#include<bits/stdc++.h>
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());
    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<(int)a.size();i++){
        for(int j=i+1;j<(int)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+(int)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--;
            }
        }
    }
    cout<<ans<<endl;
}
原文地址:https://www.cnblogs.com/stranger-/p/11225760.html