至今不懂官方题解是什么意思:答案就是popcount(n)−popcount(⌊2mn⌋)+⌊2mn⌋.
popcount是数出一个二进制数中有几个1,如0110就是2
用贪心过得比较多:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll mypow(ll x,ll n){
ll res = 1;
while(n){
if(1 & n) res = res *x;
x = x*x;
n >>= 1;
}
return res;
}
ll _2pow[31];
void initial(){
for(int i=0;i <=30;i++)
_2pow[i] = mypow(2,i);
}
int main()
{
initial();
//freopen("in.txt","r",stdin);
int n,m,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
int ans = 0;
m = m >= 31?30:m;
for(int i = m;i>=0 && n;i--){
if( n >= _2pow[i]){
int xi = n / _2pow[i];
n = n - (xi *_2pow[i]);
ans += xi;
}
}
printf("%d\n",ans);
}
return 0;
}
/*题解的做法..着实想不到,后来敲了一遍
//自己写的,比较挫..
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll mypow(ll x,ll n){
ll res = 1;
while(n){
if(1 & n) res = res *x;
x = x*x;
n >>= 1;
}
return res;
}
int popcout(ll num){
int cnt = 0;
while (num){
if(num & 1) cnt++;
num >>= 1;
}
return cnt;
}
int main()
{
int n,m;
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(m>31)m=30;
ll A = popcout(n);
ll B = popcout(n/mypow(2,m));
ll C = (ll)n/mypow(2,m);
printf("%I64d\n", A - B + C);
}
return 0;
}
*/
930

被折叠的 条评论
为什么被折叠?



