Magic Numbers CodeForces - 628D 数位DP

传送门:CodeForces - 628D

题意:定义d-magic数为d出现且只出现在偶数位上。问[l,r]内%m==0的d-magic数有多少个。

思路:一看便知是数位DP,还是很水的那种。。然而蒟蒻并不会。。

坑点:因为是大数,所以边界不能直接-1,可以用字符串模拟大数-1,也可以单独判断一下边界。

代码:

#include<bits/stdc++.h>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
const int mod=1e9+7;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int DP[2200][2200];
int DIG[2200];
int m,d,len;
int    dfs(int pos,int pre,int limit)
{
    if(pos == len)
        return    pre==0;
    if(!limit && DP[pos][pre] != -1)
        return    DP[pos][pre];
    int    end = limit ? DIG[pos] : 9;
    int    ret = 0;
    for(int i = 0;i <= end;i ++)
    {
    	if((pos&1)&&i!=d)continue;
    	if((!(pos&1))&&i==d)continue;
    	ret += dfs(pos + 1,(pre*10+i)%m,limit && (i == end)),ret%=mod;
	}    
    if(!limit)
        DP[pos][pre] = ret;
    return    ret;
}
string l,r;
bool check()
{
	int s=0;
	for(int i=0;i<len;i++)
	{
		s=s*10+DIG[i];
		s%=m;
		if(DIG[i]==d&&(!(i&1)))return false;
		if(DIG[i]!=d&&(i&1))return false;
	}
	return s==0;
}
int main()
{
	ll ans;
	std::ios::sync_with_stdio(0);
	memset(DP,-1,sizeof(DP));
	cin>>m>>d;
	cin>>l>>r;
	len=l.size();
	for(int i=0;i<len;i++)
	DIG[i]=l[i]-'0';
	ans=dfs(0,0,1);
	ans-=check();
	len=r.size();
	for(int i=0;i<len;i++)
	DIG[i]=r[i]-'0';
	cout<<(dfs(0,0,1)-ans+mod)%mod;
 	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值