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 (0≤i≤m) is non-negative.
Input
There are multiple test cases. The first line of input contains an integer T (1≤T, indicating the number of test cases. For each test case:
The first contains two integers n and m (0≤n,m≤109).
The first contains two integers n and m (0≤n,m≤109).
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\n",ans); else{ int t = _pow(2,m); ans = 0; while(k&&t){ ans+=k/t; k = k%t; t/=2; } printf("%d\n",ans); } } return 0; }