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; }