루오 구 P3413 SAC # 1 - 비트 수 멩 문제 DP 정지

주제 링크 : https://www.luogu.com.cn/problem/P3413

제목 효과 :
정의의 수단 멩 번호 : 번호 대회에서 "하위 상동 문자열이 적어도 길이의 존재".
상대 간격 \ ([L, R] \ ) 발아의 개수의 범위에서 참조.

아이디어를 문제 해결 :
사용 디지털 DP는 그것을 해결하기 위해.
정의 된 상태 \ (F [POS] [P1 ] [P2]는 \) 다음 조건을 만족하는 제도를 나타낸다 :

  • 경우 제 1 비트 기간 \ (POS \) 비트;
  • 그 숫자 앞의 그 번호의 앞에 (P1 \) \ ;
  • 그 번호의 앞에 \ (P2는 \) .

당신은의 기능을 열 수 있습니다 dfs(int pos, int p1, int p2, bool limit)해결에를 :

  • \ (POS는, P1, P2 \ ) 전술 한 바와;
  • \ (제한 \) 전류 제한 상태에 있음을 나타낸다.

주 : 상기 입력 문자열의 시작 후, 변환 입력을 시작되도록 비트들의 수는 1000이다.

다음 코드는 다음과 같습니다

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007;
long long f[1010][10][10], pow10[1010];
int a[1010];
char ch[1010];
void init() {
    memset(f, -1, sizeof(f));
    pow10[0] = 1;
    for (int i = 1; i <= 1000; i ++) pow10[i] = pow10[i-1] * 10 % MOD;
}
long long dfs(int pos, int p1, int p2, bool limit) {
    if (pos < 0) return 0;  // 因为我一旦找到回文子串会返回,所有到pos<0时还没有找到就直接返回0了
    if (!limit && p1!=-1 && p2!=-1 && f[pos][p1][p2] != -1) return f[pos][p1][p2];
    int up = limit ? a[pos] : 9;
    long long tmp = 0;
    for (int i = 0; i <= up; i ++) {
        if (p1 == i || p2 == i) {
            if (limit && i==up) {
                // tmp += num % pow10[pos] + 1; // 不能这么算,因为是大数
                long long t = 0;
                for (int j = pos-1; j >= 0; j --)
                    t = (t * 10 + a[j]) % MOD;
                tmp += t + 1;
            }
            else tmp += pow10[pos] % MOD;
        }
        else
            tmp += dfs(pos-1, p2, (p2==-1&&i==0&&pos>0)?-1:i, limit && i==up);
        tmp %= MOD;
    }
    if (!limit && p1!=-1 && p2!=-1) f[pos][p1][p2] = tmp;
    // printf("dfs pos=%d, p1=%d, p2=%d, limit=%d, tmp = %lld\n", pos, p1, p2, limit, tmp);
    return tmp;
}
long long get_num(bool minus1) {
    cin >> ch;
    int len = strlen(ch);
    for (int i = 0; i < len; i ++) a[i] = ch[len-1-i] - '0';
    // 判断是否为0
    bool all0 = true;
    for (int i = 0; i < len; i ++) if (a[i] != 0) { all0 = false; break; }
    if (all0) return 0;
    // 判断是否要减1
    if (minus1) {
        a[0] --;
        for (int i = 0; i < len; i ++) {
            if (a[i] < 0) { a[i] += 10; a[i+1] --; }
            else break;
        }
    }
    return dfs(len-1, -1, -1, true);
}
int main() {
    init();
    long long num_l = get_num(true);
    long long num_r = get_num(false);
    cout << (num_r - num_l + MOD) % MOD << endl;
    return 0;
}

추천

출처www.cnblogs.com/quanjun/p/12002278.html