1. 程式人生 > >[SCOI 2009]windy數

[SCOI 2009]windy數

lex bit com namespace div 鏈接 tin problem markdown

Description

題庫鏈接

找出在 \([A,B]\) 間滿足相鄰位差值至少為 \(2\) 的正整數個數。

\(1\leq A,B\leq 2\cdot 10^9\)

Solution

數位 \(DP\)

還是按照套路 \(f_{i,j}\)\(i\) 位數,第 \(1\) 位為 \(j\) 的滿足條件的個數。

然後計算的時候要註意若前面的位數已經不滿足了,就直接退出。

Code

//It is made by Awson on 2018.2.25
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a)) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) #define writeln(x) (write(x), putchar('\n')) #define lowbit(x) ((x)&(-(x))) using namespace std; void
read(LL &x) { char ch; bool flag = 0; for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); x *= 1-2*flag; } void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48
); } void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); } LL f[20][10], a, b; void pre() { for (int i = 0; i <= 9; i++) f[1][i] = 1; for (int i = 2; i <= 10; i++) { for (int j = 0; j <= 9; j++) { for (int k = 0; k <= j-2; k++) f[i][j] += f[i-1][k]; for (int k = j+2; k <= 9; k++) f[i][j] += f[i-1][k]; } } } LL get(int x) { int a[20], tot = 0; LL ans = 0; while (x) a[++tot] =x%10, x /= 10; for (int i = tot-1; i >= 1; i--) for (int j = 1; j <= 9; j++) ans += f[i][j]; for (int i = 1; i < a[tot]; i++) ans += f[tot][i]; for (int i = tot-1, last = a[tot]; i >= 1; i--) { for (int j = 0; j < a[i]; j++) { if (Abs(j-last) < 2) continue; ans += f[i][j]; } last = a[i]; if (Abs(a[i+1]-a[i]) < 2) break; } return ans; } void work() { pre(); read(a), read(b); writeln(get(b+1)-get(a)); } int main() { work(); return 0; }

[SCOI 2009]windy數