題意
數列的所有子數列(不一定連續)中,刪去最大元素和最小元素只差大於等於d的子數列後,剩下x個,求一個這樣的數列。
且數列長度不超過1e4,數列元素屬於 1 ~ 1e18
思路
貪心構造數列,分爲幾組數,組內元素相同,相鄰組相差d。
此時只有組內元素會產生符合要求的子數列,當第i組元素的個數位 ki 時,產生 2^ki - 1 個子數列。
要將 x 分解爲 一系列 2^ki - 1 的和,不如先考慮分爲 2^ki 的和,採用二進制位運算,多出來的單獨分組即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 10010
using namespace std;
typedef long long ll;
ll x, d, a[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%lld %lld", &x, &d);
ll now = 1, tot = 0, cnt = 0; //cnt標記正在處理x的第幾位
int tmp = 0; // 記錄非零位個數
while (x)
{
if (now > 1e18 || tot > 10000)
{
printf("-1\n");
return 0;
}
if (x & 1)
{
tmp++;
for (int i = 0; i < cnt; i++)
{
a[tot++] = now;
}
if (cnt > 0)
now += d;
}
x >>= 1;
cnt++;
}
for (int i = 0; i < tmp; i++)
{
if (now > 1e18 || tot > 10000)
{
printf("-1\n");
return 0;
}
a[tot++] = now;
now += d;
}
printf("%d\n", tot);
printf("%lld", a[0]);
for (int i = 1; i < tot; i++)
printf(" %lld", a[i]);
printf("\n");
/*
if (x <= 10000)
{
printf("%d\n", x);
ll tmp = 1;
printf("1");
for (int i = 1; i < x; i++)
{
tmp += d;
printf(" %lld", tmp);
}
printf("\n");
}
else
{
ll tot = 1, p, now = 1, pre = 1;
a[1] = 1;
int i = 2;
while (tot < x)
{
if (i > 10000)
{
printf("-1\n");
return 0;
}
for (; i <= 10000; i++)
{
p = qpow(i - pre);
if (tot + p <= x)
{
tot += p;
a[i] = now;
if (a[i] > 1e18)
{
printf("-1\n");
return 0;
}
}
else
{
if (tot == x)
{
printf("%d\n", i - 1);
printf("1");
for (int t = 2; t < i; t++)
{
printf(" %lld", a[t]);
}
printf("\n");
return 0;
}
a[i] = now + d;
now += d;
pre = i;
//cout << tot << endl;
if (a[i] > 1e18)
{
printf("-1\n");
return 0;
}
tot++;
i++;
break;
}
}
}
printf("%d\n", i - 1);
printf("1");
for (int t = 2; t < i; t++)
{
printf(" %lld", a[t]);
}
printf("\n");
}
*/
return 0;
}