题意:给出一个数组的不同子集的个数k,求出一个数列满足这个条件;
思路:当数列为1 ,2,3,,,,n的时候,不同子集的个数就为等差数列求和n * (n + 1)/2;当数列中出现两个相同的数的时候,你会发现不同子集数少了一个,
以此类推,3个的时候少了 1+ 2 = 3个,4个的时候少了1 + 2 + 3个……;
找的时候记得用二分;
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
ll a[maxn];
void Init()
{
a[1] = 1;
for(int i = 2; i < maxn; i ++)
{
a[i] = a[i - 1] + i;
}
}
int n,m;
int num[maxn];
int main()
{
int Tcase;
Init();
// cout << a[16] << endl;
// scanf("%d",&Tcase);
while( ~ scanf("%d",&n))
// while( ~ scanf("%d%d",&n,&m))
{
int pos = lower_bound(a+1,a+maxn,n) - a;
if(a[pos] == n)
{
cout << pos << endl;
for(int i = 1; i <= pos; i ++)
{
if(i == pos)
cout << i << endl;
else cout << i << " ";
}
continue;
}
while(true)
{
ll t = a[pos] - n;
int len = pos;
int lens = 0;
while(t)
{
int poss = lower_bound(a+1,a+maxn,t) - a;
if(a[poss] == t)
{
num[lens ++] = poss + 1;
// cout << poss << " " << num[lens - 1] << endl;
len -= (poss + 1);
break;
}
else
{
t -= a[poss - 1];
num[lens ++] = poss;
// cout << poss -1 << " " << num[lens - 1] << endl;
len -= (poss);
}
}
if(len < 0)
{
pos ++;
continue;
}
// cout << pos << endl;
// int ans = a[pos];
// for(int i = 0; i < lens; i ++)
// {
// cout << num[i] << " ";
// ans -= a[num[i] - 1];
// }cout << "ps" << endl;
// cout << "II" <<ans << endl;
cout << pos << endl;
for(int i = 1; i <= len; i ++)
{
cout << i << " ";
}
for(int i = 0,t = len + 1,k = len + 1; i < lens; i ++,t ++)
{
while(num[i] --)
{
if(k < pos)
cout << t << " ";
else cout << t << endl;
k ++;
}
}
break;
}
}
return 0;
}