bzoj 1026 [SCOI2009]windy数(数位DP)
2016-01-11 21:32
441 查看
1026: [SCOI2009]windy数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4550 Solved: 2039
[Submit][Status][Discuss]
Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?Input
包含两个整数,A B。Output
一个整数。Sample Input
【输入样例一】1 10
【输入样例二】
25 50
Sample Output
【输出样例一】9
【输出样例二】
20
HINT
【数据规模和约定】100%的数据,满足 1 <= A <= B <= 2000000000 。
Source
【思路】数位DP。
设f[i][j]表示i位数且最高位为j的数中windy数的个数。则有转移式:
f[i][j]=sigma{ f[i-1][k] } ( | j-k |>=2 )
统计:长度比len小的 -> 长度为len最高位比b[len]小的 -> 最高位为b[len],统计方法见代码。
需要注意的是最后一项统计时,如果枚举过程中发现n不满足windy数则不再枚举,另外还需要注意n的计入与否。
【代码】
#include<cstdio> #include<algorithm> using namespace std; const int N = 15; int f ,b ; void init() { for(int i=0;i<10;i++) f[1][i]=1; for(int i=2;i<=10;i++) for(int j=0;j<10;j++) { for(int k=0;k<=j-2;k++) f[i][j]+=f[i-1][k]; for(int k=j+2;k<10;k++) f[i][j]+=f[i-1][k]; } } int Fc(int n) { if(!n) return 0; int ans=0,len=0,flag=1; while(n) b[++len]=n%10 , n/=10; for(int i=1;i<len;i++) //统计所有长度小于 len 的 for(int j=1;j<10;j++) ans += f[i][j]; for(int j=1;j<b[len];j++) ans += f[len][j]; //长度为 len 最高位比 b[len] 小的 for(int i=len-1;i;i--) { //统计最高位为 b[len] 的 for(int j=0;j<b[i];j++) if(abs(b[i+1]-j)>=2) ans += f[i][j]; if(abs(b[i+1]-b[i])<2) { //n 不满足 不再统计后面的而且不计入 n flag=0; break; } } if(flag) ans++; //计入 n return ans; } int main() { int n,m; init(); scanf("%d%d",&n,&m); printf("%d",Fc(m)-Fc(n-1)); return 0; }
相关文章推荐
- 一套通过c# sap-rfc 完整处理内表输入输出的程序
- Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效
- <LeetCode OJ> 26. Remove Duplicates from Sorted Array
- linux + cuda7.5 + opencv2.4.8编译caffe
- 【Activiti 基础篇三】流程定义—CRUD操作
- job定时执行存储过程
- (eden)Delete character
- 结构型-适配器adapter
- 程序员面试金典——递归问题汇总
- ORACLE RAC 表决磁盘(votedisk)
- iPhone全部设备分辨率速查
- iPhone全部设备分辨率速查
- Android多点触控技术实战,自由地对图片进行缩放和移动
- Eclipse快捷键 10个最有用的快捷键
- iPhone全部设备分辨率速查
- 博客园暂停更新说明
- zend studio 快捷键
- mongodb3.2 安装配置
- 第一次听到了docker
- Ubuntu下中文输入法的安装