Time Limit: 1.0 Seconds Memory Limit:65536K
Total Runs: 253 Accepted Runs:76
Xiao Ming is very interesting for array. He given a sorted positive integer array and an integer n.
We need add elements to the array such that the sum of subset of array cover the range [1, n]. You must return the minimum number of add elements.
Xiao Ming worry about you can't understand this problem. Now, he gives you an example:
There is an array [1, 3], n = 6, the answer is 1. Because we only need to add 2 into array. After add operator, the array is [1,2,3]. The subsets are: [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3]. Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
Input
The input consists of multiple test cases. The first line contains an integer [Math Processing Error]T, indicating the number of test cases.
Each case contains two integers [Math Processing Error]m,n,[Math Processing Error]m means the number of elements in array, [Math Processing Error]n means the cover range.[Math Processing Error](1≤m≤105,1≤n≤2147483647).
Then comes a line with [Math Processing Error]m integers.
Output
Return the minimum number of add elements.
Sample Input
1 3 20 1 5 10
Sample Output
2
大致思路:
一开始想到二进制位上去了,觉得每个数的二进制位都有个贡献之类的,结果还是too naive啊,跟正解差的太多。
首先对子集A的元素排个序,然后假设当前子集中最大的数为a[i-1],能够覆盖的范围是1~mx,那么如果a[i]>mx+1的话,必须要插入mx+1这个数才能使覆盖的范围仍旧连续,而插入mx+1,会使得覆盖的范围变成2*mx+1,此时再比较a[i]与当前的mx的大小,直到a[i]<=mx+1时加入a[i]会使得覆盖的范围变成mx+a[i],一直这么考虑下去就ok。
复杂度分析:
首先对于数m来说,最多只需要log2(m)个数就可以满足题意了,那么插入的复杂度应该就是O(n+logm),之前还需要排序,就是O(nlogn),总的的复杂度即O(nlogn)了。
#include<string>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const double eps=1e-7;
ll arr[100005];
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
ll now=1;
int m;
ll n;
scanf("%d%lld",&m,&n);
for(i=0;i<m;i++)scanf("%lld",&arr[i]);
ll zsm=0;
int cnt=0;
for(i=0;i<m;i++)
{
while(arr[i]>zsm+1)
{
zsm+=(zsm+1);
cnt++;
}
zsm+=arr[i];
if(zsm>=n)break;
}
// cout<<zsm<<" "<<cnt<<endl;
while(zsm<n)
{
zsm+=(zsm+1);
cnt++;
}
// cout<<zsm<<" "<<cnt<<endl;
printf("%d\n",cnt);
}
}