bzoj1026
http://www.lydsy.com/JudgeOnline/problem.php?id=1026
数位dp。。。
首先我们先把没有限制的dp出来,然后分类讨论,如果最高位比这个数的最高位小或者比这个数短的方案先加上去,然后讨论最高位等于这个数的情况。
比如说54321,我们把<50000的东西全部弄好了。
然后枚举,从a[0]-1开始,我们把(50000,53999)的加上,然后把(54200,54299)的加上,然后把(54300,54319)的加上,注意我们传的参数,最后把(54320,54321)的加上。
因为dp[i]表示第i位,所以每次我们加上的是从第i位到第一位的方案,只要i位和上一位满足条件,就可以加。
总结:先统计宽松的,最后统计天际线附近的,不断逼近。。。
#include<bits/stdc++.h> using namespace std; int A, B; int a[20], dp[20][20]; int solve(int n) { int ret = 0; a[0] = 0; while(n) a[++a[0]] = n % 10, n /= 10; for(int i = 1; i < a[0]; ++i) for(int j = 1; j <= 9; ++j) ret += dp[i][j]; for(int i = 1; i < a[a[0]]; ++i) ret += dp[a[0]][i]; for(int i = a[0] - 1; i; --i) { for(int j = 0; j < a[i]; ++j) if(abs(j - a[i + 1]) >= 2) ret += dp[i][j]; if(abs(a[i] - a[i + 1]) < 2) break; } return ret; } int main() { for(int i = 0; i <= 9; ++i) dp[1][i] = 1; for(int i = 2; i <= 10; ++i) for(int j = 0; j <= 9; ++j) for(int k = 0; k <= 9; ++k) if(abs(j - k) >= 2) dp[i][j] += dp[i - 1][k]; scanf("%d%d", &A, &B); printf("%d\n", solve(B + 1) - solve(A)); return 0; }