TOJ 4168 I-The brute force problem(数论)

来源:互联网 发布:梦想世界跨服传输数据 编辑:程序博客网 时间:2024/06/05 10:56

4168.   I-The brute force problem
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

13 201 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);    }}





阅读全文
0 0
原创粉丝点击