牛客月赛7-明七暗七-(数位dp+二分)

D

题意:
就是说一群人做一圈,轮流从1开始报数,如果这个数字包含7或者是7的倍数那么就拍一次手。现在问你数n以后,第m次拍手的时候的数字应该是多少。

思考:
看了看,不像思维题,再一看,这明显就是数位dp了,然后问你什么时候第m拍手,那就二分看看什么时候满足。当时傻逼了,是n以后,我以为包含n,一直错。
其实呢,当时还是在怀疑是不是自己的dp限制加少了,其实,我们考虑的是是否为7的倍数,是否包含7,只要这两个限制有了,就是满足的。就是只要dp里面包含所有题目要求限制的东西,那么就是不会多算和少算的。是否为7的倍数,我们用当前%7的值是多少来限制,是否包含7就用suc来限制。

代码:

int T,n,m,k;
int va[N];
int dp[20][20][2];

int dfs(int pos,int limit,int lead,int sum,int suc)
{
	if(!pos) return (sum%7==0||suc);
	if(!limit&&!lead&&dp[pos][sum][suc]!=-1) return dp[pos][sum][suc];
	int res = 0;
	int up = limit?va[pos]:9;
	for(int i=0;i<=up;i++)
	{
		int limit_t = limit&&(i==up);
		int lead_t = lead&&(i==0);
		int sum_t = (sum*10+i)%7;
		int suc_t = suc||(i==7);
		res += dfs(pos-1,limit_t,lead_t,sum_t,suc_t);
	}
	if(!limit&&!lead) dp[pos][sum][suc] = res;
	return res;
}

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

bool check(int mid)
{
	if(f(mid)-f(n)>=m) return true;
	return false;
}

signed main()
{
	IOS;
	cin>>n>>m;
	int l = n,r = 1e15;
	while(l<r)
	{
		int mid = l+r>>1;
		if(check(mid)) r = mid;
		else l = mid+1;
	}
	cout<<l;
	return 0;
}

总结:
多多思考啊,注意题目细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值