CF1862D Ice Cream Balls

发布时间 2023-08-25 14:58:17作者: One_JuRuo

思路

容易发现如果长度为 \(x\) 的序列 \(a\) 中每个数都不一样,那么无论数是什么,方案数总是一样,这种情况下方案数是 \(\frac{x\times (x-1)}2\)

我们再对序列 \(a\) 添加一些已经存在的数,如果添加了一个 \(k\),则会方案数会加 \(1\),也就是多了一个 \(\{k,k\}\) 的方案,而且其他的方案是存在的,如果再添加一个 \(k\) 则方案数不会增加,所以添加两个及以上的相同数字是无意义的。

所以我们可以通过添加一些已经存在且不同的数来使答案增加,最多可以新添加 \(x\) 个数,也就是总方案数为 \(\frac{x\times (x-1)}2+1 \sim \frac{x\times (x-1)}2 +x=\frac{x\times (x-1)+2\times x}2=\frac{x\times (x+1)}2\) 之间的数都可以,而 \(\frac{x\times (x+1)}2\) 还可以用长度为 \(x+1\) 的每个数都不同的序列得到,再大一点的方案数就又可以在长度为 \(x+1\) 的新序列加若干个已存在的不同的数得到。

所以对于每个 \(n\) 都存在答案。

那么,我们再来思考如何得到答案。

对于 \(n=\frac{x\times (x-1)}2\) 的情况,答案为 \(x\)

考虑如何得到 \(x\)

首先不考虑 \(n\) 是完全平方数的情况,则有 \(\lfloor \sqrt n \rfloor^2 < n < \lceil \sqrt n \rceil ^2\),且 \(\lfloor \sqrt n \rfloor +1 = \lceil \sqrt n \rceil\)

\(s=\lfloor \sqrt n \rfloor\),如果 \(n=s\times(s+1)\) 那么答案就是 \(s+1\)

否则,我们需要找到小于 \(n\) 形如 \(x=t\times (t+1)\) 中最大的 \(x\)

我们可以用 \(t+1\) 个不同的数再多加 \(n-x\) 个已存在不同的数达成方案数为 \(n\) 的情况,答案就是 \(t+1+n-x\)

再考虑 \(n\) 为完全平方数的情况,则 \(n\) 一定不能通过若干个不同的数构成的序列达到,那么也是第二种情况,解法也与第二种一样。

AC code

#include<bits/stdc++.h>
using namespace std;
int t;
long long n;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld",&n);
		long long s=sqrt(1llu*n*2);
		if(s*(s+1)/2==n) printf("%lld\n",s+1);
		else
			for(long long j=s-3;;++j)
				if(j*(j+1)/2>n)//找到最小的x
				{
					printf("%lld\n",j+(n-(j-1)*j/2));break;//注意:此时的x=j*(j-1)/2,所以答案是j+(n-x)不要搞错了。
				}
	}
}