洛谷P3413 萌数
https://www.luogu.com.cn/problem/P3413
回文长度2或者3就可以裁定,值得注意的是dp[pos][pre][ppre]可能应对3334321和5554321(都有321),所以要引入最新的变量才行。
dp[pos][pre][ppre][sum],具体套了板子,返回的时候记得让pre和ppre的数字不是前导0
#include<iostream>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
int T, n, m, len, a[2020];
ll l, r, dp[1010][14][13][3];
ll mod = 1e9 + 7;
// 记录答案 ppre是1能算
ll dfs(int pos, int pre, int ppre, ll sum, int d, int lead, int limit)
//pos搜到的位置
//pre前一位数
//st当前公差最大差值
//sum整个数字的最大价值
//d共差
//lead判断是否有前导0
//limit判断是否有最高位限制
{
if (pos > len) return sum;//dp结束
//记录状态(计划搜索)
//注意d有负数,最小可以到-9,所以记录时数组下标是d+10
if ((dp[pos][pre][ppre][sum] != -1 && (!limit) && (!lead)) && d == 1) return dp[pos][pre][ppre][sum] %= mod;
ll ret = 0;
int res = limit ? a[len - pos + 1] : 9;//最高位最大值
for (int i = 0; i <= res; i++)
{
//有前导0且这位也是前导0,一切不变只有位数变化
if ((!i) && lead) {
ret += dfs(pos + 1, 0, 0, 0, 0, 1, limit && (i == res));
ret %= mod;
}
//有前导0但这位不是前导0(这位是数字的最高位)开始有前一位,一个数形成等差数列
else if (i&&lead) {//当前位置是最高位
ret += dfs(pos + 1, i, 0, 0, 0, 0, limit && (i == res));
ret %= mod;
}
else {//前面已经有非0的数字了lead = 0
ll su = (i == pre) || (sum == 1);
if (d == 1 && i == ppre) su = 1;
ret += dfs(pos + 1, i, pre, su, 1, 0, limit && (i == res));
ret %= mod;
}
}
ret %= mod;
//没有前导0和最高限制时可以直接记录当前dp值以便下次搜到同样的情况可以直接使用。
return (!limit && !lead && d == 1) ? dp[pos][pre][ppre][sum] = ret : ret;
}
int list[2020];
ll cal(string x,int cl)
{
len = 0;
for (int i = 0; i < x.length(); i++) {
list[i] = x[i] - '0';
}
list[x.length()-1] -= cl;
for (int i = x.length() - 1; i >= 0; i--) {
if (list[i] < 0) {
list[i] = 9;
list[i - 1] --;
}
}
int f = 0;
for (int i = 0; i < x.length(); i++) {
if (f == 0 && list[i] == 0) list[i] = -1;
if (list[i] > 0) f = 1;
}
for (int i = x.length() - 1; i >= 0; i--) {
if (list[i] == -1) break;
a[++len] = list[i];
}
memset(dp, -1, sizeof dp);
return dfs(1, 0, 0, 0, 0, 1, 1);//-38是随便赋的其实赋成-10就行了……
}
string sn;
int main()
{
cin >> sn;
ll ans = cal(sn, 1);
cin >> sn;
ll cns = cal(sn, 0);
cout << (cns - ans + mod) % mod << endl;
//l是0的时候要特别注意!
//printf("%lld\n", part(r) - part(l-1));
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号