hdu 5747(数学,贪心)

Aaronson

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 239    Accepted Submission(s): 156


Problem Description
Recently, Peter saw the equation x0+2x1+4x2+...+2mxm=n. He wants to find a solution (x0,x1,x2,...,xm) in such a manner that i=0mxi is minimum and every xi (0im) is non-negative.
 
Input
There are multiple test cases. The first line of input contains an integer T (1T105), indicating the number of test cases. For each test case:

The first contains two integers n and m (0n,m109).
 
Output
For each test case, output the minimum value of i=0mxi.
 
Sample Input
10 1 2 3 2 5 2 10 2 10 3 10 4 13 5 20 4 11 11 12 3
 
Sample Output
1 2 2 3 2 2 3 2 3 2
 
Source
 
题意: x0+2x1+22x2+...+2m*xm = n 现在已知 n,m,求解最小的 sum(xi)(0<=i<=m).
题解:昨天刷bestcoder别人三分钟就AC了,我用了20+min才有思路,好惭愧..我的想法如果 n 化成二进制的位数小于 m+1 ,那么只要在这m位中添加 0 1 即可得到n,所以最小的和就是 n 化成二进制中间的 1 的个数,然后当 n 的位数大于 m+1 ,那么我就在这 m+1 位上面添加数字,使得其接近 n,我们想如果能够在越高位添加数字,那么就会越接近 n,所以我们从 2m 开始枚举,然后贪心即可。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int _pow(int a,int n){
    int ans = 1;
    while(n){
        if(n&1) ans = ans*a;
        a=a*a;
        n>>=1;
    }
    return ans;
}

int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--){
        int n,m;
        scanf("%d%d",&n,&m);
        int k = n;
        int cnt = 0,ans=0;
        while(n){
            if(n%2==1) ans++;
            cnt++;
            n/=2;
        }
        if(cnt<=m+1) printf("%d
",ans);
        else{
            int t = _pow(2,m);
            ans = 0;
            while(k&&t){
                ans+=k/t;
                k = k%t;
                t/=2;
            }
            printf("%d
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liyinggang/p/5700125.html