codeforces628DMagic Numbers

Consider the decimal presentation of an integer. Let's call a number d-magic if digit d appears in decimal presentation of the number on even positions and nowhere else.

For example, the numbers 1727374171 are 7-magic but 7771233471 are not 7-magic. On the other hand the number 7 is 0-magic123 is 2-magic34 is 4-magicand 71 is 1-magic.

Find the number of d-magic numbers in the segment [a, b] that are multiple of m. Because the answer can be very huge you should only find its value modulo 109 + 7 (so you should find the remainder after dividing by 109 + 7).

Input

The first line contains two integers m, d (1 ≤ m ≤ 20000 ≤ d ≤ 9) — the parameters from the problem statement.

The second line contains positive integer a in decimal presentation (without leading zeroes).

The third line contains positive integer b in decimal presentation (without leading zeroes).

It is guaranteed that a ≤ b, the number of digits in a and b are the same and don't exceed 2000.

Output

Print the only integer a — the remainder after dividing by 109 + 7 of the number of d-magic numbers in segment [a, b] that are multiple of m.


分析:这是一道数位DP题。数位DP题的基本特性是给你两个数,然后在这两个数字之间找到符合约束条件的数的个数,

数位DP有一个模板可以用于套,那么问题的解决就在于DP的过程中对符合条件的数进行筛选,这一题是简单题,DP过

程加个IF语句就可以了。

然后来讲讲在DFS的三个参数值那个jud在算法中的运用,jug=1时表示此时数字是满位,例如考虑数字3的时候,当我对

0,1,2,进行求值的时候,jug就为0了。

jug的值在算法中的记忆化搜索有着重要的地位,为什么在jug=0时可以直接返回dp值而jug=1的时候不可以呢?.主要是

当jug为零的时候是枚举0-9的,而jug=1的是时候只枚举下一位m(0-m),如果在jug=1时也直接返回状态会变多进而

导致答案也比所求答案大,那么就不正确了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2100;
typedef long long LL;
int num[maxn],len;
LL dp[maxn][maxn];
const int MOD=1e9+7;
char ax[maxn],bx[maxn];
int m,d;
LL dfs(int pos,int ok,int jud)
{
     if(pos==len)return ok==0;
     if(!jud&&dp[pos][ok]!=-1)return dp[pos][ok];
     LL ans=0;
     int sz=jud?num[pos]:9;
     for(int i=0;i<=sz;i++)
     {
         if(pos%2==0&&i==d)continue;
         if(pos%2!=0&&i!=d)continue;
         ans+=dfs(pos+1,(ok*10+i)%m,jud&&(sz==i));
         ans%=MOD;
     }
     if(!jud)
        dp[pos][ok]=ans;
     return ans;
}
LL Cou(char* s)
{
    int pos=0;
    for(int i=0;i<len;i++)
    {
        int index=s[i]-'0';
        num[i]=index;
    }
    return dfs(0,0,1);
}
int jud(char* s)
{
    int temp=0;
    for(int i=0;i<len;i++)
    {
        num[i]=s[i]-'0';
        if(num[i]==d&&i%2==0)
            return 0;
        if(num[i]!=d&&i%2==1)
            return 0;
        temp=(temp*10+num[i])%m;
    }
    return temp==0;

}
int main()
{

    memset(dp,-1,sizeof(dp));
    scanf("%d%d",&m,&d);
    scanf("%s%s",&ax,&bx);
    len=strlen(ax);
    //cout<<Cou(ax)<<endl;
    printf("%d",(Cou(bx)%MOD-Cou(ax)%MOD+jud(ax)+MOD)%MOD);

    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值