codedorces 1305E. Kuroni and the Score Distribution

题意:

给定一个n,m。要求构造一个单调递增的序列,要求a[i]+a[j]=a[k]的数量恰好等于m
1 < = n < = 5000 , 0 < = m < = 1 0 9 1<=n<=5000,0<=m<=10^9

分析:

首先思考如何构造得到的满足条件的三元对尽可能多,那就是从1,2,3…n这样构造,那么对于每个加进来的数,对答案的贡献就是当前存在的数除以2。那么当贡献超过m时,就可以将下标往右移,这个数为a[index]+a.back(),对答案的贡献就是剩余元素个数除以2。
对于已经n个元素,但贡献小于m时,就是无解。若已经到达了m,那么我们如何构造剩下的元素呢?
这时我们就从可取的最大值出发,以每次减少原来的最大值+1的速度减少,因为n较小,且前面的数都是连续的,所以新的这些数根本不会小于最大值的一半。这样就能保证剩下的数不会对答案产生贡献。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> ans;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;
	cin >> n >> m;
	if( n == 1 )
	{
		if( m == 0 ) cout << 1 << '\n';
		else cout << -1 << '\n';
		return 0;
	}
	ans.push_back(1);
	ans.push_back(2);  
	while( m )
	{
		if( ans.size() == n ) break;
		int t = ans.size() / 2;
		if( m > t )
		{
			m -= t;
			ans.push_back(ans[0]+ans.back()); 
		}else
		{
			int index = 0;
			while( m != t )
			{
				index ++;
				t = ( ans.size() - index ) / 2;
			}
			m = 0;
			ans.push_back(ans[index]+ans.back()); 
		}
	}
	if( m ) cout << -1 << '\n';
	else
	{
		int t = ans.back() + 1;
		int begin = 1e9;
		while( ans.size() != n )
		{
			begin -= t;
			ans.push_back(begin); 
		}
		sort(ans.begin(),ans.end()); 
		for (int i = 0; i < ans.size(); i++)
		{
			cout << ans[i];
			if( i == ans.size() - 1 ) cout << '\n';
			else cout << ' ';
		}
	}
	return 0;
}

发布了103 篇原创文章 · 获赞 6 · 访问量 7024

猜你喜欢

转载自blog.csdn.net/weixin_44316314/article/details/104663403