BZOJ 1026: [SCOI2009]windy數
阿新 • • 發佈:2017-12-28
print 基礎 開心 register div zoj 水題 printf clu
二次聯通門 : BZOJ 1026: [SCOI2009]windy數
/* BZOJ 1026: [SCOI2009]windy數 水題開心 數位dp f[i][j]表示一個i位的數字的第i位是j的數字有幾個 設 s (x)為[0,x)的答案 怎麽求s(x)? 設x有t位,我們先找到所有t - 1的符合題意的數 然後從高到低一位一位得確定為原數字x對應位上的數字 在此基礎上累計方案數就好了 就能求出[0,x)的答案了 然後s (M + 1) - s (N)即可 */ #include <cstdio> #definerg register #define Max 20 int f[Max][Max], d[Max]; inline int abs (int x) { return x < 0 ? -x : x; } int Calc (int x) { int c = 0, res = 0; rg int i, j, k; for (; x; d[++ c] = x % 10, x /= 10); for (i = 1; i < c; ++ i) for (j = 1; j <= 9; ++ j) res += f[i][j]; for (i = c; i; -- i) {for (j = (i == c); j < d[i]; ++ j) if (i == c || abs (j - d[i + 1]) >= 2) res += f[i][j]; if (i < c && abs (d[i + 1] - d[i]) < 2) break; } return res; } int main (int argc, char *argv[]) { rg int i, j, k; for (i = 0; i <= 9; ++ i) f[1][i] = 1; for (i = 1; i <= 10; ++ i) for (j = 0; j <= 9; ++ j) { for (k = 0; k <= j - 2; ++ k) f[i + 1][k] += f[i][j]; for (k = j + 2; k <= 9; ++ k) f[i + 1][k] += f[i][j]; } int N, M; scanf ("%d%d", &N, &M); printf ("%d", Calc (M + 1) - Calc (N)); return 0; }
BZOJ 1026: [SCOI2009]windy數