BZOJ 1026 【SCOI2009】 windy数
2016-07-20 21:18
316 查看
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 。
这是我写的第一道数位dp题,心里好开心>_<
因为网上我找不到什么好的题解,所以我觉得最好我自己再写一篇虽然也不一定写得好其实主要还是我太弱了,看不懂
首先,我们可以预处理出在没有任何限制的情况下的windy数。这里认为最高位是第$1$位,则可以令$dp_{i,j}$表示第$i$位填$j$的方案数,我从低位往高位转移,显然$$dp_{i,j}=\sum_{k=0}^{9} dp_{i+1,k}(| k-j| \ge 2)$$
接下来,我们可以处理出$f_i$表示在第$i$位取该位最大值的方案数。设这个数第$i$位为$a_i$,则转移为$$f_i=\sum_{k=0}^{a_{i+1}-1} dp_{i+1,k}(| a_{i}-k| \ge 2)$$
当然,如果$|a_{i+1}-a_i| \ge 2$ ,$f_i$还要加上$f_{i+1}$。
然后,我们可以考虑如何统计答案。既然要求$[l,r]$之间的windy数个数,那么显然可以转为前缀和的差,也就是区间$[1,r]$的答案减去区间$[1,l-1]$的答案。
那么,我们只需知道小于等于$x$的windy数个数即可。我们来考虑下。
首先,我们可以先找到这个数第一个不为$0$的位置$w$。然后,这个位置显然可以放$1$到$a_w-1$,这部分的答案为$\sum_{i=1}^{a_{w}-1} dp_{w,i}$。然后,当这个位置放$a_w$时方案数就是$f_w$。
接下来我们还要处理掉在位置$w$填$0$的情况。设这个数长度为$len$,我们只需再统计一下$\sum_{i=w+1}^{len} \sum_{j=1}^{9}dp_{i,j}$就可以了。
下面是代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define INF 2147483647 using namespace std; typedef long long llg; int a[2][20],g[20][10],n,ans,x,y,z; int f[20]; void init(int x){ int now=0,ww=1; while(!a[x][ww] && ww<=n) ww++; memset(g,0,sizeof(g)); memset(f,0,sizeof(f)); f =1; for(int i=0;i<=9;i++) g [i]=1; for(int i=n-1;i;i--){ for(int j=0;j<=9;j++) for(int k=0;k<=9;k++) if(abs(j-k)>=2) g[i][j]+=g[i+1][k]; for(int j=0;j<a[x][i+1];j++) if(abs(a[x][i]-j)>=2) f[i]+=g[i+1][j]; if(abs(a[x][i]-a[x][i+1])>=2) f[i]+=f[i+1]; } for(int i=ww+1;i<=n;i++) for(int j=1;j<=9;j++) now+=g[i][j]; if(ww<=n){ for(int i=1;i<a[x][ww];i++) now+=g[ww][i]; now+=f[ww]; } if(x) ans+=now; else ans-=now; } int main(){ File("a"); scanf("%d %d",&x,&y); x--;z=y; while(z) n++,z/=10; for(int i=n;i;i--){ a[0][i]=x%10,x/=10; a[1][i]=y%10,y/=10; } init(0); init(1); printf("%d",ans); return 0; }
相关文章推荐
- Screen
- JavaScript基础函数,事件
- tjut 5400
- C++的类为什么要用指针
- codeforces水题100道 第二十四题 Codeforces Beta Round #85 (Div. 2 Only) A. Petya and Strings (strings)
- 有关 phpmyadmin登陆中遇到The requested URL /phpmyadmin was not found on this server的解决方法
- 冒泡排序的优化方法
- 【CF 666B】World Tour
- Sort Colors
- UVA-10970 Big Chocolate
- navicat 破解方法及下载
- algorithm 题集五 (16.07.20)
- 程序实体与关键字
- JS的作用域和声明提前
- 作业
- 关于汇编ARM指令DCD
- Rank(该学生第几名)
- POJ-1276 Alignment ( 多重背包)优化版
- HDU 1157.
- jquery 杂文