题目背景
本题由世界上最蒟蒻最辣鸡最撒比的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; }