zoukankan      html  css  js  c++  java
  • bnuoj24252 Divide

    Alice and Bob has found a island of treasure in byteland! They find N kinds of treasures on the island, and each kind of treasure has a certain number, and as in byteland, the value of each treasure will be a power of 2, such as 1,2,4,8 ...

    Now the only problem is how to divide treasures fairly, they need to divide the treasures into two parts, and the value of each part is the sum of all treasures' in this part, they want to make the difference between the value of two parts as small as possible, can you help them?

    Input


    First line of the input is a single integer T(1 <= T <= 20), indicating there are T test cases.

    For each test case, the first line contain one integer N(2 <= N <= 10^5), indicate the different kinds of treasures.

    Then N line followed, each line will have follow two integer ai(0 <= ai <= 10^5) and xi(0 <= xi <= 10^9), indicate there are xi i-th treasures, and the value of each one is 2^ai.

    Output

    For each case, you should output a single line, first output "Case #t: ", where t indicating the case number between 1 and T, then a string with only '0' and '1' followed, indicate the minimum difference in binary representation, find more details in samples.

    Sample Input

    3
    2
    0 2
    2 1
    4
    0 1
    1 1
    2 1
    3 1
    4
    0 2
    1 1
    2 1
    3 1

    Sample Output

    Case #1: 10
    Case #2: 1

    Case #3: 0

    这题是道二进制想法题,给你n种2^a[i]次,num[i]件的物品,问你怎样分配为两堆物品能使两堆的差值最小。这里我们可以把读入的每件物品都用二进制储存起来,用num[i]表示二进制第i位上的数,用jinwei[i]表示这一位是否由前一位进位得到。

    然后从高位到低位循环,直到没有进位的且为1的那位退出,那么最小的差值即为当前的位数所表示的数减去其低位加起来的总数。为什么这样是对的呢,因为如果是0或者2,那么一定可以平分,如果是1,且是由进位得到的,那么这个进位可以表示为2个较低位的数。而且2^i>2^(i-1)+2^(i-2)+2^(i-3)+...+2^0,所以这样差值一定是最小的。


    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define inf 0x7fffffff
    #define maxn 106000
    struct node{
        ll num,v;
    }a[maxn],b[maxn];
    
    ll jinwei[maxn],num[maxn],ans[maxn];
    
    int main()
    {
        ll n,m,i,j,T,tot,cnt,cas=0;
        scanf("%lld",&T);
        while(T--)
        {
            memset(num,0,sizeof(num));
            memset(jinwei,0,sizeof(jinwei));
            memset(ans,0,sizeof(ans));
            scanf("%lld",&n);
            for(i=1;i<=n;i++){
                scanf("%lld%lld",&a[i].v,&a[i].num);
                num[a[i].v+1]+=a[i].num;
            }
            tot=0;
            for(i=1;i<=105000;i++){
                if(num[i]==0)continue;
                if(num[i]==1){
                    tot=i;continue;
                }
                tot=i;
                if(num[i]%2==0){
                    num[i+1]+=num[i]/2;jinwei[i+1]=1;
                    num[i]=0;
                }
                else{
                    num[i+1]+=num[i]/2;jinwei[i+1]=1;
                    num[i]=1;
                }
            }
            j=10000000000;
            for(i=tot;i>=1;i--){
                if(num[i]==0)continue;
                if(num[i]==1){
                    if(jinwei[i]==1)continue;
                    else{
                        j=i;break;
                    }
                }
            }
            if(j==10000000000){
                cas++;
                printf("Case #%lld: 0
    ",cas);continue;
            }
            if(j==1){
                cas++;
                printf("Case #%lld: 1
    ",cas);continue;
            }
            for(i=j-1;i>=1;i--){
                ans[i]=1-num[i];
            }
            ans[1]++;
            tot=0;
            for(i=1;i<=105000;i++){
                if(ans[i]==0)continue;
                if(ans[i]==1){
                    tot=i;continue;
                }
                tot=i;
                if(ans[i]%2==0){
                    ans[i+1]+=ans[i]/2;
                    ans[i]=0;
                }
                else{
                    ans[i+1]+=ans[i]/2;
                    ans[i]=1;
                }
            }
            cas++;
            printf("Case #%lld: ",cas);
            for(i=tot;i>=1;i--){
                printf("%lld",ans[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    


  • 相关阅读:
    java内存回收机制
    scala学习
    [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
    linux 进程的创建
    linux中的进程和线程
    linux 文件系统
    gdb 调试程序
    makefile
    linux下的gcc编译器
    socket 网络编程
  • 原文地址:https://www.cnblogs.com/herumw/p/9464641.html
Copyright © 2011-2022 走看看