또 한 번 비트DP 물문제.

6557 단어 dp

Description


구간 [a, b]에 1을 포함하는 수량을 구합니다.예를 들어 구간[111112]은 전체 구간에 두 개의 수를 포함하는데 각각 11112111은 3개의 1을 포함하고 112는 2개의 1을 포함하기 때문에 구간[11112]은 모두 5개를 포함한다.

Input


다중 테스트 데이터.
각 그룹의 테스트 데이터는 두 개의 정수 a, b, 1 <=a <=b <=10^18을 포함한다.

Output


각 그룹의 테스트 출력은 한 줄로 1의 수량을 표시하고 결과mod 10^9+7.

Sample Input


111 112
1 1000

Sample Output


5
301
 
 
코드는 다음과 같습니다.
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;

const int MOD = int(1e9)+7;
typedef long long LL;
LL f[20]; // f[i]     i ,  1   
int bit[20];
LL num;

LL _pow(int b) {
    LL ret = 1;
    for (int i = 0; i < b; ++i) {
        ret *= 10;
    }
    return ret;
}

LL dfs(int p, int e) {
    if (p == -1) return 0;
    if (!e && f[p]!=-1) return f[p];
    LL ret = 0;
    int LIM = e ? bit[p] : 9;
    for (int i = 0; i <= LIM; ++i) {
        if (i == 1) {
            ret += dfs(p-1, e&&(i==LIM));
            ret %= MOD;
            if (e&&(i==LIM)) {
                ret += (num % _pow(p) + 1)%MOD;
                ret %= MOD;
            } else {
                ret += _pow(p) % MOD;
                ret %= MOD;
            }
        } else {
            ret += dfs(p-1, e&&(i==LIM));
        }
    }
    if (!e) {
        f[p] = ret;
    }
    return ret;
}

int cal(LL x) {
    if (!x) return 0;
    num = x;
    int idx = 0;
    while (x) {
        bit[idx++] = x % 10;
        x /= 10;
    }
    return dfs(idx-1, 1);
}

int main() {
    LL a, b;
    memset(f, 0xff, sizeof (f));
    while (scanf("%lld %lld", &a, &b) != EOF) {
        printf("%d
", (cal(b)-cal(a-1)+MOD)%MOD); } return 0; }

 

좋은 웹페이지 즐겨찾기