[Luogu] P3413 萌数

题目背景

本题由世界上最蒟蒻最辣鸡最撒比的SOL提供。

寂月城网站是完美信息教室的官网。地址:已和谐 。

题目描述

辣鸡蒟蒻SOL是一个傻逼,他居然觉得数很萌!

好在在他眼里,并不是所有数都是萌的。只有满足“存在长度至少为2的回文子串”的数是萌的——也就是说,101是萌的,因为101本身就是一个回文数;110是萌的,因为包含回文子串11;但是102不是萌的,1201也不是萌的。

现在SOL想知道从l到r的所有整数中有多少个萌数。

由于答案可能很大,所以只需要输出答案对1000000007(10^9+7)的余数。

输入输出格式

输入格式:

输入包含仅1行,包含两个整数:l、r。

输出格式:

输出仅1行,包含一个整数,即为答案。

输入输出样例

输入样例#1:
1 100
输出样例#1: 
10
输入样例#2: 
100 1000
输出样例#2:
253

说明

记n为r在10进制下的位数。

对于10%的数据,n <= 3。

对于30%的数据,n <= 6。

对于60%的数据,n <= 9。

对于全部的数据,n <= 1000,l < r。

题目解析

数位DP,难度一般

因为数据比较水所以我先预处理出1~1000的萌数

处理需要技巧,因为萌数有两种:相邻数相同和隔一个数相同,直接做会难以去重。所以我们搞一搞,用容斥就不需要去重了。

dp[i][j][k] 表示第i位是j,第i-1位是k的萌数数量,进行数位dp即可。

Code

#include<bits/stdc++.h>
using namespace std;

const long long MAXN = 1000 + 5;
const long long p = 1e9 + 7;

long long dp[MAXN][10][10];
//到第i位时,i位是j,i-1位是k,有多少不萌的数。
long long ans;
string l,r;

long long find_ans(long long n,string s) {
    long long x = -1,y = -1;
    long long tot = 0,res = 0;
    bool flag = true;
    for(long long i = 0; i < n; i++) {
        tot = (tot * 10 + s[i] - '0') % p;
    }
    for(long long i = 1; i < n; i++) {
        for(long long j = 1; j <= 9; j++) {
            for(long long k = 0; k <= 9; k++) {
                res = (res + dp[i][j][k]) % p;
            }
        }
    }
    if(n > 1) res += 10;
    for(long long i = n; i > 1; i--) {
        long long tmp = s[n - i] - '0';
        for(long long j = 0; j < tmp; j++) {
            if(i == n && j == 0) continue;
            for(long long k = 0; k <= 9; k++) {
                if(x != j && y != j && j != k && k != x) {
                    res += dp[i][j][k];
                    res %= p;
                }
            }
        }
        if(tmp == x||tmp == y) {
            flag = false;
            break;
        }
        y = x;
        x = tmp;
    }
    if(flag) {
        for(long long j = 0; j <= s[n - 1] - '0'; j++) {
            if(j != y && j != x) {
                res++;
                res %= p;
            }
        }
    }
    return (tot + 1 - res + p) % p;
}

int main() {
    cin >> l >> r;
    for(long long i = 2; i <= 1000; i++) {
        for(long long j = 0; j <= 9; j++) {
            for(long long k = 0; k <= 9; k++) {
                if(j == k) continue;
                for(long long l = 0; l <= 9; l++) {
                    if(j != l && k != l) dp[i][j][k] += dp[i - 1][k][l];
                }
                if(i == 2) dp[i][j][k]++;
                dp[i][j][k] %= p;
            }
        }
    }
    ans = (long long)(find_ans(r.length(),r) - find_ans(l.length(),l)) % p;
    for(long long i = 1; i <= l.length(); i++) {
        if(l[i] == l[i - 1] || (i > 1 && l[i] == l[i - 2])) {
            ans++;
            ans %= (long long)p;
            break;
        }
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/floatiy/p/9476986.html