洛谷 P3413

题目链接: P3413 SAC#1 - 萌数

题目大意

详见题目

solution

有个弱化版:P6754 [BalticOI 2013 Day1] Palindrome-Free Numb
正着想, 好想么? 不好想. 那我们正难则反的来考虑

然后对于 \(ans_{l, r}\) 可以转化为 \(ans_{1, r} - ans_{1, l - 1}\)

\(f_{i, j, k}\) 表示长度为 \(i\) 最高位为 \(j\) 的次高位为 \(k\) 的非萌数的个数

\(f_{i, j, k} += \sum\limits_{\text{k != j && k != l && j != l}} f_{i - 1, k, l}\)

对于\(ans_{1, r}\) 我们简单的进行讨论即可

小问题 :

  1. 注意前导零的问题
  2. 因为 \(l\) 位数太大 我们无法简单的对 \(l - 1\) 进行求解, 所以我们直接对 \(l\) 单独处理即可

那么答案就是 \(ans_{l, r} + ans_l\)

Code:

/**
*    Author: Aliemo
*    Data: 
*    Problem: 
*    Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>

#define int long long
#define rr register

#define inf 1e9
#define MAXN 2010

using namespace std;

const int mod = 1e9 + 7;

inline int read() {
	int s = 0, f = 0;
	char ch = getchar();
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void print(int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) print(x / 10);
	putchar(x % 10 + 48);
}

char l[MAXN], r[MAXN];

int f[MAXN][20][20], a[MAXN];

int len, tot, ans;

inline int f_pow(int x, int y) {
	int ans = 1;
	while (y)  {
		if (y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans % mod;	
}

inline void init() {
	for (rr int i = 2; i <= 1000; i++) 
		for (rr int j = 0; j <= 9; j++)
			for (rr int k = 0; k <= 9; k++) {
				if (j == k) continue;
				for (rr int l = 0; l <= 9; l++)
					if (k != l && j != l) 
						f[i][j][k] = (f[i - 1][k][l] + f[i][j][k]) % mod;
				if (i == 2) f[i][j][k]++;
				f[i][j][k] %= mod;
			}
}

inline int solve(char s[]) {
	memset(a, 0, sizeof a);
	tot = 0;
	int len = strlen(s);
	if (len == 1) return 0;
	bool t = 1;
	int res = 0, last1 = -1, last2 = -1, sum = 0;
	for (rr int i = len; i >= 1; i--) {
		a[i] = s[len - i] - '0';
		sum = (sum * 10 + a[i]) % mod;
	}
	sum++;
	res += 10;
	for (rr int i = 2; i < len; i++)             //前导零
		for (rr int j = 1; j <= 9; j++)
			for (rr int k = 0; k <= 9; k++)
				res = (res + f[i][j][k]) % mod;
	for (rr int i = len; i >= 2; i--) {
		int x = a[i];
		for (rr int j = 0; j < x; j++) {
			if (i == len && !j) continue;
			for (rr int k = 0; k <= 9; k++)
				if (last1 != j && last2 != j && j != k && last1 != k)
					res = (res + f[i][j][k]) % mod;
		}
		if (last1 == x || last2 == x) {
			t = 0;
			break;
		}
		last2 = last1, last1 = x;
	}
	if (t) 
		for (rr int i = 0; i <= a[1]; i++)
			if (i != last2 && i != last1) 
				res = (res + 1) % mod;
	return (sum - res + mod) % mod;
}

signed main() {
	init();
	cin >> l >> r;
	ans = (solve(r) - solve(l) + mod) % mod;
	int t = strlen(l);
	for (rr int i = 1; i < t; i++)
		if (l[i] == l[i - 1] || (l[i] == l[i - 2] && i > 1)) {
			ans = (ans + 1) % mod;
			break;
		}
	cout << ans << "\n";
}
posted @ 2020-11-17 14:07  Aliemo  阅读(103)  评论(1编辑  收藏  举报