Ozon Tech Challenge 2020 (Div.1 + Div.2, Rated) E. Kuroni and the Score Distribution(思维+构造)

题目链接
在这里插入图片描述
在这里插入图片描述
题意:要你构造出这样一个序列:
1、所有序列元素满足a【i】在【1,1e9】范围内;
2、所有元素满足单调递增
3、存在a【i】+a【j】=a【k】,i<j<k这样的三元组的个数刚好为m个。
思路:一个思维构造题,先想想怎么刚好构造出m个这样的三元组,我们构造一个最简单的序列1 2 3 4 5.。。。我们可以发现如果是这样的一个序列,对于每一个a【i】它对答案的贡献都是0 0 1 1 2 2 3 3.。。
这样的话当到达i的时候它的三元组个数是可以O(1)求的(我特地写了个check函数求到i的时候的三元组个数,其实有点多余),如果刚好等于m还好,如果到i的时候三元组个数大于m了,那么ans【i】就不能等于i,这个时候我们只需要往前找m-check(i-1)个二元组满足剩下的即可。什么意思呢?比方说n=15,m=39,一开始构造的肯定是1 2 3 4 5 6 7 8 9 10 11 12 13但是到14的时候三元组个数大于m所有13后面不能填14,我们发现这个时候三元组个数还缺3个,那么我们往前推2*3个也就是8+13=9+12=10+11,这样就可以把m给补齐了,13后面理所应当应该填21,那么如果后面还有呢?考虑到如果继续后面有序的填的话可能会大于m,比赛的时候也没有多想,干脆直接从1e9往后推,每次每次都是ans【i】=ans【i+1】-maxx-1,maxx就是我们一开始有序的填的最后一个数也就是我们上面对应的21。因为是1e9的大小肯定不会有多余的三元组。
PS:比赛的时候时间紧迫来不及,所以代码奇丑无比,关键思路懂了就行,赛后幸好没有被fst。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+1;
const ll inf=1e9;
ll ans[maxn];
ll check(ll x)
{
	ll t=(x-1)/2;
	if(x&1) return t+t*(t-1);
	else return t*2+t*(t-1);
}
int main()
{
	ll n,m,k=0,cnt=0,flag=0,maxx;
	cin>>n>>m;
	ans[1]=1;ans[2]=2;
	ans[n]=inf;
	maxx=n+1; 
	if(m==0) flag=1;
	else{
		for(int i=3;i<=n;++i)
	{
		 if(check(i)<=m) ans[i]=i;
		else 
		{
			ll t=m-check(i-1);
			if(check(i-1)==m) t=0;
			cnt=m;
		if(t>0) ans[i]=ans[i-1]+ans[i-2*t];
			flag=1;
			k=(t>0)?i:(i-1);
			maxx=(t>0)?ans[i]:ans[i-1];
			break;
		}
	}
	}
	if(flag)
	{
	for(int i=n-1;i>k;--i)
	ans[i]=ans[i+1]-maxx-1;
	}
	if(check(n)<m)
	{
		cout<<-1<<endl;return 0;
	}
	for(int i=1;i<=n;++i) cout<<ans[i]<<" ";
} 
发布了171 篇原创文章 · 获赞 0 · 访问量 5791

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104651090