Leading 1s-(数位dp)

A

题意:
就是给你一个n,求出f(1)+…+f(n),f(x)的值是,x前面连续1的个数。

思考:
看一眼范围,和按位来考虑那就是数位dp,然后就正常的位,是否连续,总数,这三维就可以了。

代码:

int T,n,m;
int va[N];
int cnt,ans;
int dp[M][M][M];

int f(int x);
int dfs(int pos,int vis,int sum,int limit,int lead);

signed main()
{
	IOS;
	cin>>n;
	cout<<f(n);
	return 0;
}

int dfs(int pos,int vis,int sum,int limit,int lead)
{ 	
	if(not pos) return sum;
	if(!limit&&!lead&&dp[pos][vis][sum]!=-1) return dp[pos][vis][sum];
	int up = limit?va[pos]:9;
	int res = 0;
	for(int i=0;i<=up;i++)
	{	
		int limit_t = limit&&(i==up),lead_t = lead&&(i==0); //通用的
		if(lead) res += dfs(pos-1,(i==1),(i==1),limit_t,lead_t); //一般都是lead这里有区分要特定处理
		else
		{
			int vis_t = vis&&(i==1);
			if(vis) res += dfs(pos-1,vis_t,sum+(i==1),limit_t,lead_t);
			else res += dfs(pos-1,vis_t,sum,limit_t,lead_t);
		}
	}
	if(!limit&&!lead) dp[pos][vis][sum] = res;
	return res;
}

int f(int x)
{
	mem(dp,-1);
	cnt = 0;
	while(x)
	{
		va[++cnt] = x%10;
		x /= 10;
	}
	return dfs(cnt,1,0,1,1);
}

总结:
多多复习,总结一下维的确定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值