C. Subsequence Counting(构造)

Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)

题意

构造一个序列,其子序列中满足 m a x − m i n > = d max - min >= d maxmin>=d的数量为x。

思路

Let’s call a subsequence valid if the difference of maximum element and minimum element is less than d.
  ~  
For an array of size n with all the elements equal, there are 2n - 1 non-empty subsequences and all of them are valid. This is because for any subsequence, the difference of maximum element and minimum element is always zero.
  ~  
We will use this observation in constructing the answer. Let’s look at the binary representation of X. If the ith bit is set in X, we will add i equal elements (let’s say y) in our final array. However this would give us 2i - 1 non-empty valid subsequences. To correct this, we will add a separate element y + d in the final array so that the final contribution of ith bit becomes 2i. We will carry out the same process for all the bits, keeping a counter of the previous.
  ~  
In this way, the length of the final array will never exceed 600 elements.

Expected Complexity : O(logX * logX)

任意一个含有n个相同的数的序列,其满足条件的子序列个数为 2 n − 1 2^n-1 2n1。所以可以用二进制拆分的思想,将x进行拆分。每次求出一个满足条件 2 n − 1 ≤ x 2^n - 1 \le x 2n1x 的整数n。初次在数组中加入n个1,之后每次加入的数都增加d。这样便可保证数组中最大的数尽量小。且题目数据范围内均有解。

#include<cstdio>
#include<queue>
#include<set>
#include<cstdlib>
#include<string.h>
#include<string>
#include<iostream>
#include<cmath>
#include<unordered_map>
#include<map>
#include<algorithm>
#define endl "\n"
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define ft first
#define sd second
#define pll pair<ll, ll>
#define pii pair<int, int>
#define ll long long int
#define ull unsigned long long int
#define mt(a,b) memset(a, b, sizeof a)
//#define int long long
const double PI = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int INF = 0x7fffffff;
using namespace std;
const int N = 2e5 + 7, M = 1e6 + 10;
ll a[N], b[N];
int main()
{
	IOS;
	ll x, d; cin >> x >> d;

	ll k = 0, start = 1;
	while (x)
	{
		int t = log(x + 1) / log(2);
		for(int i = 1; i <= t; i++)
		{
			a[++k] = start;
		}
		x -= (ll)pow(2, t) - 1;
		start += d;
	}

	if (k > 40000) cout << -1 << endl;//可有可无
	else
	{
		cout << k << endl;
		for (int i = 1; i <= k; i++)
			cout << a[i] << " ";
	}
	

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

to cling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值