C. Prairie Partition
time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output
It can be shown that any positive integer x can be uniquely represented as x = 1 + 2 + 4 + ... + 2k - 1 + r, where k and r are integers, k ≥ 0, 0 < r ≤ 2k. Let's call that representation prairie partition of x.
For example, the prairie partitions of 12, 17, 7 and 1 are:
12 = 1 + 2 + 4 + 5,
17 = 1 + 2 + 4 + 8 + 2,
7 = 1 + 2 + 4,
1 = 1.
Alice took a sequence of positive integers (possibly with repeating elements), replaced every element with the sequence of summands in its prairie partition, arranged the resulting numbers in non-decreasing order and gave them to Borys. Now Borys wonders how many elements Alice's original sequence could contain. Find all possible options!
Input
The first line contains a single integer n (1 ≤ n ≤ 105) — the number of numbers given from Alice to Borys.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1012; a1 ≤ a2 ≤ ... ≤ an) — the numbers given from Alice to Borys.
Output
Output, in increasing order, all possible values of m such that there exists a sequence of positive integers of length m such that if you replace every element with the summands in its prairie partition and arrange the resulting numbers in non-decreasing order, you will get the sequence given in the input.
If there are no such values of m, output a single integer -1.
Examples
input
8
1 1 2 2 3 4 5 8
output
2
input
6
1 1 1 2 2 2
output
2 3
input
5
1 2 4 4 4
output
-1
Note
In the first example, Alice could get the input sequence from [6, 20] as the original sequence.
In the second example, Alice's original sequence could be either [4, 5] or [3, 3, 3].
题意:给出一个序列,问这个序列可以由多少个数分解而来,分解方式如题。
思路:分解数ans的上限为1的数目,加如可以分解为x组,其中x<count[1],那么[x,count[1]]的都可以作为答案,因为将1提取出来又是新的一组。那么可以二分出可分解的最小组数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
int n;
long long fac[55];
int cnt[55];
int need1[55];
vector<long long> e;
bool check(int x)
{
int have[55];
int need[55];
int minn=x;
have[51]=0;
for(int i=0;i<=50;i++)
{
have[i]=need[i]=0;
minn=min(minn,cnt[i]);
have[i]=minn;
int id=i;
if(id>0)
id--;
need[id]+=(cnt[i]-have[i]);
}
for(int i=0;i<=50;i++)
{
have[i]=have[i]-have[i+1];
}
int res=0;
for(int i=0;i<=50;i++)
{
res+=(need[i]+need1[i]);
int tp=min(res,have[i]);
res-=tp;
have[i]-=tp;
}
if(res==0)
return true;
else
return false;
}
int bin(int t)
{
int l=1,r=t;
while(l<r)
{
int mid=(l+r)/2;
if(check(mid))
{
r=mid;
}
else
{
l=mid+1;
}
}
if(check(r))
return r;
else
return t+1;
}
int main()
{
fac[0]=1;
for(int i=1;i<=50;i++)
{
fac[i]=fac[i-1]*2;
}
while(~scanf("%d",&n))
{
for(int i=0;i<=50;i++)
cnt[i]=0,need1[i]=0;
e.clear();
for(int i=0;i<n;i++)
{
long long tp;
scanf("%lld",&tp);
int f=0;
for(int j=0;j<=50;j++)
{
if(fac[j]==tp)
{
cnt[j]++;
f=1;
break;
}
}
if(f==0)
e.push_back(tp);
}
for(int i=0;i<e.size();i++)
{
int id=log2(e[i]);
if(fac[id]==e[i])
id--;
need1[id]++;
//cout<<id<<endl;
}
int ans=bin(cnt[0]);
if(ans>cnt[0])
printf("-1\n");
else
{
for(int i=ans;i<=cnt[0];i++)
printf("%d ",i);
printf("\n");
}
}
}