Codeforces 628D. Magic Numbers 數位DP


傳送門

我又來水一發啦。寫這個題犯了很多比較傻的錯誤。。一開始寫的等於號我還以爲應該是等於等於 就改了 樣例還過了 其實就應該是一個等於。。。二維的記憶化竟然被我改成了一維還死活看不出哪錯了我真是。。。

還是老套路, pos位置, id標記a還是b ,lim當前位置是否有限制,res餘數,st是否是第一個數字。

狀態 d[pos][res];

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int maxn = 2024;
const int mod = 1e9 + 7;

char a[maxn],b[maxn],s[maxn];
int m, n, len;
long long d[maxn][maxn];

long long solve(int pos, int id, int lim, int res, int st){
    if(pos < 0) return res == 0;
    if(!lim && d[pos][res] != -1) return d[pos][res];
    int up = 9;
    if(lim) up = id ? b[pos] - 48 : a[pos] - 48;
    long long ans = 0;
    if(!((len - pos)& 1)){
        if(up >= n) ans = (ans + solve(pos - 1, id, lim&&up == n, m?(res*10 + n)%m : 0, 1)) % mod;
    } else {
        for(int i = 0;i <= up;i ++){
            if(i == n) continue;
            if(st || i) ans = (ans + solve(pos - 1, id, lim&&i == up, m?(res*10 + i)%m : 0, 1)) % mod;
        }
    }
    if(!lim) d[pos][res] = ans;
    return ans;
}

int main(){
    while(~scanf("%d",&m)){
        memset(d, -1, sizeof d);
        scanf("%d",&n);
        scanf("%s%s",a,b);
        len = strlen(b);
        reverse(a,a + len);
        reverse(b,b + len);
        long long ans = solve(len - 1, 1, 1, 0, 0);
        if(string(a) == "0") ;
        else {
            memset(d, -1, sizeof d);
            a[0] --;
            for(int i = 0;i < len - 1;i ++){
                if(a[i] >= 48) break;
                a[i] += 10;
                a[i + 1] --;
            }
            if(a[len - 1] == '0') ;
            else ans = (ans - solve(len - 1, 0, 1, 0, 0)+ mod) % mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章