题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=6148
题意:对于每个数n,问有多少<=n的数是Valley数,即数字的各个数位之间不会先递增后递减。
f[len][j][0/1/2]记录长度为len,最高位是j时的可行的数字个数,其中0表示数字是平的,1表示数字出现过递减但未出现过递增,2表示出现过递增,可能出现过递减。
先预处理出,然后进行dp即可。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define ll long long
#define ull unsigned long long
#define BUG cout<<"*************************"<<endl
using namespace std;
const ll mod = 1000000007;
const int maxn = 5e3 + 10;
const int maxm = 1e6 + 10000;
const double eps = 1e-8;
ll f[101][10][3];
int a[101];
string s;
ll dp(int len) {
ll ans = 1;
for (int i = 1; i < a[len]; ++i) {
ans += f[len][i][1] + f[len][i][2] + f[len][i][0];
}
ans %= mod;
bool ok = 1;
for (int i = len - 1; i; --i) {
if (ok) {
for (int j = 0; j < a[i]; ++j) {
if (j <= a[i + 1]) ans += f[i][j][0] + f[i][j][1] + f[i][j][2];
else ans += f[i][j][0] + f[i][j][1];
}
} else {
for (int j = a[i + 1]; j < a[i]; ++j) {
ans += f[i][j][0] + f[i][j][1];
}
}
ans %= mod;
if (!ok && a[i] < a[i + 1]) {
ans--;
break;
}
if (a[i] > a[i + 1])ok = 0;
}
for (int i = len - 1; i; --i) {
for (int j = 1; j <= 9; ++j)
ans += f[i][j][0] + f[i][j][1] + f[i][j][2];
ans %= mod;
}
return ans;
}
ll solve(string t) {
memset(a, 0, sizeof(a));
int pos = 0;
int ct = 0;
while (ct < t.size() && t[ct] == '0')++ct;
for (int i = (int) (t.size() - 1); i >= ct; --i) {
a[++pos] = t[i] - '0';
}
if (pos == 0)return 0;
return dp(pos);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
for (int i = 0; i <= 9; ++i)f[1][i][0] = 1;
for (int i = 2; i <= 100; ++i) {
for (int j = 0; j <= 9; ++j) {
f[i][j][0] = 1;
for (int k = j + 1; k <= 9; ++k) {
f[i][j][1] += f[i - 1][k][1] + f[i - 1][k][0];
}
f[i][j][1] += f[i - 1][j][1];
f[i][j][2] += f[i - 1][j][2];
for (int k = 0; k < j; ++k) {
f[i][j][2] += f[i - 1][k][2] + f[i - 1][k][0] + f[i - 1][k][1];
}
f[i][j][0] %= mod;
f[i][j][1] %= mod;
f[i][j][2] %= mod;
}
}
int _;
cin >> _;
while (_--) {
cin >> s;
cout << solve(s) << endl;
}
return 0;
}