P6218 [USACO06NOV] Round Numbers S

链接Miku

数位dp,定义\(dp_{i,j,k}\)为到了第i位有j个零并且有k个前导零的方案数

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int l,r;
int dp[50][50][50];
int n1[50];
int n2[50];
int p;
int cnt;
int dfs(int pos,int num,int leadz,int li,int numz){
	int ret=0;
	if(pos>p){
		if((!leadz )&&num>=(p-num-numz)) return 1;
		return 0;
	}
	if(dp[pos][num][numz]!=-1&&leadz==0&&li==0){
		return dp[pos][num][numz];
	}
	int lim= (li==1? n1[p-pos+1]:1);
	for(int i=0;i<=lim;++i){
		 ret+=dfs(pos+1,num+(i==0&&leadz==0),leadz&&(i==0),li&&i==lim,numz+(leadz&&(i==0)));
	}
	if(leadz==0&&li==0)
	dp[pos][num][numz]=ret;
	return ret;
}
int solve(int x){
	 p=0;
	while(x){
		n1[++p]=x%2;
		x/=2;
	}
	memset(dp,-1,sizeof(dp));
	return dfs(1,0,1,1,0);
}
int main(){
	scanf("%d%d",&l,&r);
	cout<<solve(r)-solve(l-1);
	return 0;
}
posted @ 2020-09-01 21:29  Simex  阅读(81)  评论(0编辑  收藏  举报