首页 > 代码库 > bzoj1026
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; }
bzoj1026
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。