题意:
给你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; }