关键词:数位dp、求前缀和、换角度求和、统计1-m所有数位中0的个数
题意:统计[m,n]所有数的二进制表示中0的个数
解法:按照每一位0的个数进行统计。先计算1-m中所有数位中0的个数。
1.第i位(2的i-1幂次)非0:该位为0的总个数=该位的高位数大小l*10^(i-1)。因为当第i位取0时,比i位低的所有位可以取任意元素,因此取法共10^(i-1)种;而比i位高的位可以取高位数大小l种元素。
2.第i位为0:当高位不取当前数时,比i位低的所有位仍可以取任意元素。(l-1)*10(i-1);当高位取当前数时,比i位低的所有位仅能取低位数大小+1(从
00...0−ai−1ai−2a1
)
拓展:
1.求[m,n]所有数的k进制表示中x出现的次数
依照上述思路对每一位进行检索:
1)若该位值
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#define lowbit(x) x&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
#define rad 10000
long long n,m;
ll f(ll m){
ll l,r,base,ans,now;
l=m,ans=r=0,base=1;
while(l>=10){//最高位不能是0
now=l%10;
l/=10;
if(now) ans+=l*base;
else ans=ans+(l-1)*base+(r+1);
r=r+now*base;
base*=10;
}
return ans;
}
int main(){
//freopen("a.txt","r",stdin);
while(scanf("%lld%lld",&m,&n)!=EOF){
if(n==-1&&m==-1) break;
ll ans=f(n)-f(m-1);
if(m==0) ans++;
printf("%lld\n",ans);
}
}