icodelab 等边三角形

描述

小明的手中有一堆长短不一的小木棒,小明随机从这一堆中选取3根,看是否能拼成一个三角形,显然成功的概率是非常高的,现在小明想提高难度,

他随机的从这堆木棒中选取4根,并且期待着能拼成一个等边三角形,显然这种可能性是比较低的。现在给你n根木棒,问有多少种选取方法。

因为选取的方法可能非常多,需要最终答案对1e9+7取模。

输入

输入两行

第一行n,表示总共有n根木棒;

第二行总共有n个数,表示每根木棒的长度

输出

输出一个数,表示成功选取的方法总数

输入样例 1

4
2 2 4 4

输出样例 1

1

提示

n<=100,000;

木棒长度<=5000

思路

排列A(n,m)=n×(n-1).(n-m+1)=n!/(n-m)!(n为下标,m为上标,以下同)
组合C(n,m)=P(n,m)/P(m,m) =n!/m!(n-m)!

该题当i=j时,

  该长度木棍及1/2长度木棍均≥2时,ans+=a[i]*(a[i]-1)/2*(a[i<<1]*(a[i<<1]-1)/2 ans+=C(i,2)+C(j,2);

  A长度木棍,B木棍均≥1,A+B木棍≥2时,ans+=a[i]*a[j]*(a[i+j]*(a[i+j]-1)/2 ans+=C(i+j,2)+i+j;

代码:

#include
#include
#include
#include
#include
using namespace std;

const int N=5010;
const int Mod=1e9+7;

int n,x;
long long ans,a[N];

int main () {
	scanf("%d",&n);
	while(n--) {
		scanf("%d",&x);
		a[x]++;
	}
	for(int i=1; i<=5000; i++)
		for(int j=i; j<=5000; j++) {
			if(i+j>5000)
				break;
			if(i==j) {
				if(a[i]>=2&&a[i<<1]>=2)
					ans=(ans+(a[i]*(a[i]-1)/2LL%Mod*(a[i<<1]*(a[i<<1]-1)/2)%Mod))%Mod;
			} else {
				if(a[i]>=1&&a[j]>=1&&a[i+j]>=2)
					ans=(ans+(a[i]*a[j]%Mod*(a[i+j]*(a[i+j]-1)/2)%Mod))%Mod;
			}
		}
	printf("%lld\n",ans);
	return 0;
}

 

转载于:https://www.cnblogs.com/mysh/p/11306455.html

你可能感兴趣的:(icodelab 等边三角形)