/* https://www.luogu.com.cn/problem/P2602 */
#include <iostream>
using namespace std;
// arr[i][j]: 小于等于(i+1)位数的全排列中j的个数
long long arr[12][10];
// pre[i]: 小于等于(i+1)位数中的前导0个数
long long pre[12];
long long pow(int n)
{
long long res = 1;
for (int i = 0; i < n; ++i)
res *= 10;
return res;
}
void calc(long long num, long long (&ans)[10])
{
int i = 0, j, k, bits = 0, data[12];
long long t = num;
while (t)
{
++bits;
data[i++] = t % 10;
t /= 10;
}
for (j = 0; j < 10 && bits > 1; ++j) //[1, 10^(bits-1))
ans[j] += arr[bits-2][j];
t = pow(bits-1);
for (j = 1; j < data[bits-1]; ++j)
ans[j] += t;
if (data[bits-1] > 1) // [10^(bits-1), data[bits-1]*10^(bits-1) - 1)
for (j = 0; j < 10; ++j)
ans[j] += arr[bits-2][1] * (data[bits-1] - 1);
for (i = 0; i < (bits-1); ++i)
{
t = pow(i);
if (i < 2)
{
if (i == 0) // 处理最低位
{
for (j = 0; j <= data[i]; ++j)
++ans[j];
for (k = i+1; k < bits; ++k)
if (data[i] == 0)
++ans[data[k]];
else
ans[data[k]] += (data[i]+1);
}
else
{
for (j = 0; j < 10; ++j)
ans[j] += data[i];
for (j = 0; j < data[i]; ++j)
ans[j] += t;
for (k = i+1; k < bits; ++k)
ans[data[k]] += t * data[i];
}
}
else
{
if (data[i] > 0)
{
for (k = 0; k < 10; ++k)
ans[k] += t * i / 10 * data[i];
for (j = 0; j < data[i]; ++j)
ans[j] += t;
for (k = i+1; k < bits; ++k)
ans[data[k]] += t * data[i];
}
}
}
}
int main()
{
long long a, b, t;
cin >> a >> b;
int i, j;
for (i = 0; i < 10; ++i)
arr[0][i] = 1;
pre[0] = 1;
for (i = 1; i < 12; ++i)
{
t = pow(i);
for (j = 0; j < 10; ++j)
arr[i][j] = t + arr[i-1][j] * 10;
pre[i] = t + pre[i - 1];
}
for (i = 1; i < 12; ++i)
arr[i][0] -= pre[i];
long long ans[10] = { 0 };
long long res[10] = { 0 };
if (a > 1)
calc(a-1, res);
else
res[0] = 1;
calc(b, ans);
for (j = 0; j < 10; ++j)
cout << ans[j] - res[j] << " ";
cout << endl;
return 0;
}
/* https://www.luogu.com.cn/problem/P2657
f[i][j]: 具有i位,最高位数字为j,满足windy数定义的数的个数。
状态转移: 第i位的值为j,设第i-1位的值为k,
根据windy数定义只要满足abs(k-j) >= 2就可以进行状态转移
状态转移方程:
f[i][j] = if (abs(k-j) >= 2) { ∑f[i-1][k], (k∈[0,9] }
*/
#include <iostream>
#include <string.h>
using namespace std;
int f[11][10];
int dp(int n)
{
int bits = 0, res = 0;
int arr[11];
while (n)
{
arr[bits++] = n%10;
n /= 10;
}
int i, j, pre = -2;
// 处理 bits位数[1x...x, n]
for (i = bits-1; i >= 0; --i)
{
for (j = !!(i == bits-1); j < arr[i]; ++j)
if (abs(j - pre) >= 2)
res += f[i+1][j];
if (abs(arr[i] - pre) < 2)
break;
pre = arr[i];
if (i == 0) // n 是 windy 数
++res;
}
// 处理带有前导0的数,即小于bits位的数[1, 0x...x], bits-1位x
for (i = 1; i < bits; ++i)
for (j = 1; j <= 9; ++j)
res += f[i][j];
return res;
}
int main()
{
int a, b, i, j, k;
cin >> a >> b;
for (i = 0; i <= 9; ++i)
f[1][i] = 1;
for (i = 2; i < 11; ++i)
for (j = 0; j <= 9; ++j)
for (k = 0; k <= 9; ++k)
if (abs(j - k) >= 2)
f[i][j] += f[i-1][k];
int ans = dp(b);
if (a > 1)
ans -= dp(a-1);
cout << ans << endl;
return 0;
}
//https://www.luogu.com.cn/problem/P3311
#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
const int MOD = 1000000007;
const int N = 1501;
//当前从高到低已经填了i位(即在AC自动机上走过了i条边),此时停在标号为j的节点上,当前是否正好贴着上界
//dp[i][j][0]: 当前位置(i)的值不能超过(小于)所给整数的对应位(s[i])
//dp[i][j][1]: 当前位置的值等于所给整数的对应位(之前已经有一位小于所给整数的对应位置)
long long dp[N][N][2];
int tot;
int tr[N][10]; // tr[p]['c']=u: p 通过字符'c'指向u;还被用于更新转移边
bool e[N]; // e[u]: 节点u是结尾
int fail[N];
void insert(char *s)
{
int u = 0;
for (int i = 0; s[i] != '\0'; ++i)
{
if (tr[u][s[i]-'0'] == 0) // 不在Trie中,插入当前结点
tr[u][s[i]-'0'] = ++tot;
u = tr[u][s[i]-'0'];
}
e[u] = true;
}
void build()
{
queue<int> qu;
// 0: root node
for (int i = 0; i < 10; ++i)
if (tr[0][i])
qu.push(tr[0][i]);
while (qu.size() > 0)
{
int u = qu.front();
qu.pop();
for (int i = 0; i < 10; ++i)
{
int v = tr[u][i];
if (v)
{
fail[v] = tr[fail[u]][i];
qu.push(v);
e[v] |= e[fail[v]];
//cout << "fail[" << v << "]: " << fail[v] << endl;
}
else //将不存在的字典树的状态链接到了失配指针的对应状态
tr[u][i] = tr[fail[u]][i];
//cout << "tr[" << u << "][" << char(i+'0') << "]: " << tr[u][i] << endl;
}
}
tr[0][0] = 0; // 特殊处理包含前导0的模式串
}
inline void add(long long &x, long long y) { x = (x + y) % MOD; }
int main()
{
char s[N];
char str[N];
cin >> s;
int i, j, k, m, len = strlen(s);
cin >> m;
for (i = 0; i < m; ++i)
{
cin >> str;
insert(str);
}
build();
dp[0][0][1] = 1;
for (i = 0; i < len; ++i)
for (j = 0; j <= tot; ++j)
if (!e[j])
{
for (k = 0; k < 10; ++k)
{
if (!e[tr[j][k]])
{
add(dp[i+1][tr[j][k]][0], dp[i][j][0]);
//cout << "dp[" << i+1 << "][" << tr[j][k] << "][0]: " << dp[i+1][tr[j][k]][0] << " <-- " << "dp[" << i << "][" << j << "][0]: " << dp[i][j][0] << ", tr[" <<j << "][" << k << "]: " << tr[j][k] << endl;
if (k < (s[i]-'0')) {
add(dp[i+1][tr[j][k]][0], dp[i][j][1]);
//cout << "<<<< dp[" << i+1 << "][" << tr[j][k] << "][0]: " << dp[i+1][tr[j][k]][0] << " <-- " << "dp[" << i << "][" << j << "][1]: " << dp[i][j][1] << ", tr[" <<j << "][" << k << "]: " << tr[j][k] << endl;
}
if (k == (s[i]-'0')) {
add(dp[i+1][tr[j][k]][1], dp[i][j][1]);
//cout << "==== dp[" << i+1 << "][" << tr[j][k] << "][1]: " << dp[i+1][tr[j][k]][1] << " <-- " << "dp[" << i << "][" << j << "][1]: " << dp[i][j][1] << ", tr[" <<j << "][" << k << "]: " << tr[j][k] << endl;
}
}
}
//cout << "\n\n";
}
long long ans = 0;
for (j = 0; j <= tot; ++j)
if (!e[j])
{
add(ans, dp[len][j][0]);
add(ans, dp[len][j][1]);
}
cout << ans - 1 << endl;
return 0;
}