[LUOGU3413] SAC#1 - 萌数
题目背景
本题由世界上最蒟蒻最辣鸡最撒比的SOL提供。
寂月城网站是完美信息教室的官网。地址:http://191.101.11.174/mgzd 。
题目描述
辣鸡蒟蒻SOL是一个傻逼,他居然觉得数很萌!
好在在他眼里,并不是所有数都是萌的。只有满足“存在长度至少为2的回文子串”的数是萌的——也就是说,101是萌的,因为101本身就是一个回文数;110是萌的,因为包含回文子串11;但是102不是萌的,1201也不是萌的。
现在SOL想知道从l到r的所有整数中有多少个萌数。
由于答案可能很大,所以只需要输出答案对1000000007(10^9+7)的余数。
输入输出格式
输入格式:输入包含仅1行,包含两个整数:l、r。
输出格式:输出仅1行,包含一个整数,即为答案。
输入输出样例
说明
记n为r在10进制下的位数。
对于10%的数据,n <= 3。
对于30%的数据,n <= 6。
对于60%的数据,n <= 9。
对于全部的数据,n <= 1000,l < r。
随便写写
f[i][j][k][0/1],决策到第i位,上一位的数字是j,上上位的数字是k,是否曾经出现过回文串, 的总数。
然后就记忆化搜索一下,记得判断前一位和前前一位是否合法...
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define int long long inline int read() { int res=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define reg register #define mod 1000000007 int l, r; int f[1005][10][10][2]; int wei[1005], cnt; inline int dp(int pos, int lst1, int lst2, bool hav, bool flag, bool fir, bool sec) { //是否有限制 if (pos == 0) return hav; if (!fir and !sec and !flag and f[pos][lst1][lst2][hav] != -1) return f[pos][lst1][lst2][hav] % mod; int lim = flag ? wei[pos] : 9; int ans = 0; for (reg int i = 0 ; i <= lim ; i ++) { if (i == lst1 and !fir) ans = (ans + dp(pos - 1, i, lst1, 1, flag && i == wei[pos], fir && i == 0, sec && lst1 == 0)) % mod; else if (i == lst2 and !fir and !sec) ans = (ans + dp(pos - 1, i, lst1, 1, flag && i == wei[pos], fir && i == 0, sec && lst1 == 0)) % mod; else ans = (ans + dp(pos-1, i, lst1, hav, flag && i == wei[pos], fir && i == 0, sec && lst1 == 0)) % mod; } if (!flag and !fir and !sec) f[pos][lst1][lst2][hav] = ans % mod; return ans % mod; } signed main() { memset(f, -1, sizeof f); int res1 = 0, res2 = 0; string a; cin >> a; cnt = 0; for (reg int i = a.length() - 1 ; i >= 0 ; i --) wei[++cnt] = a[i] - '0'; int k = 1; if (wei[1]) wei[1]--; else {while(wei[k] == 0) wei[k] = 9, k++; wei[k]--;} res1 = dp(cnt, 0, 0, 0, 1, 1, 1) % mod; cnt = 0; cin >> a; for (reg int i = a.length() - 1 ; i >= 0 ; i --) wei[++cnt] = a[i] - '0'; res2 = dp(cnt, 0, 0, 0, 1, 1, 1) % mod; printf("%lld\n", (res2 - res1 + mod) % mod); return 0; }