CF817B Makes And The Product

洛谷题面

考前写题解 \(\rm rp++\)。

题目大意

给定 \(n\) 个数 \(a[1\cdots n]\) 问你满足 \(a[i]\times a[j]\times a[k]\) 的值最小,且 \(i<j<k\) 的有序对有几个?

题目分析

很妙的一道题。

来一个 \(\operatorname{O(n~log~n)}\) 的做法。

看到求三个数相乘的最小值,再看到 \(3\le n\le10^5\) 的数据范围,妥妥的 \(\log~n\) 啊!

可以马上想到将数组升序排列一遍,然后看整段序列有多少个数与 \(a[3]\) 相等,答案即为 \(tmp\)。

接下来分类讨论:

  • 当 \(a[1]=a[2]=a[3]\) 时,直接在 \(tmp\) 里选 \(3\) 个数出来即可。

答案为

\[C_{tmp}^3 \]

\[=\dfrac{tmp!}{(tmp-3)!\times 3!} \]

\[=\dfrac{tmp\times(tmp-1)\times(tmp-2)\times\cdots\times 2\times1}{(tmp-3)\times(tmp-4)\times\cdots\times2\times1\times3\times2\times1} \]

\[=\dfrac{tmp\times(tmp-1)\times(tmp-2)}{3\times2\times1} \]

  • 当 \(a[1]\neq a[2]\) 但 \(a[2]=a[3]\) 时,第一个必然应该选择,剩下的就从 \(tmp\) 中选 \(2\) 个出来即可。

答案为

\[C_{tmp}^2 \]

\[=\dfrac{tmp!}{(tmp-2)!\times2!} \]

\[=\dfrac{tmp\times(tmp-1)}{2\times1} \]

  • 其他情况。

这个时候,前两个数必然应该选择,剩下一个数直接在 \(tmp\) 里任意选 \(1\) 个即可。

故此时输出 \(tmp\)。

代码

const int ma=100005;

int a[ma];

int n;

#undef int

int main(void)
{
	#define int long long
	
	n=read();
	
	for(register int i=1;i<=n;i++)
	{
		a[i]=read();
	}
	
	sort(a+1,a+n+1);
	
	int tmp=0;
	
	for(register int i=1;i<=n;i++)
	{
		if(a[i]==a[3])
		{
			tmp++;
		}
	}
	
	if(a[1]==a[2] && a[2]==a[3])
	{
		printf("%lld\n",tmp*(tmp-1)*(tmp-2)/(3*2*1));
	}
	
	else if(a[2]==a[3])
	{
		printf("%lld\n",tmp*(tmp-1)/2);
	}
	
	else
	{
		printf("%lld\n",tmp);
	}
	
	return 0;
}

你看我熬夜写的这么认真,不点个赞吗 \(\mathcal{QwQ}\)。

上一篇:“取件帮”微信小程序宣传视频链接及内容介绍


下一篇:如何搭建个人博客网站(Mac)