Description
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?
Input
包含两个整数,A B。
Output
一个整数
Sample Input
【输入样例一】
1 10
【输入样例二】
25 50
1 10
【输入样例二】
25 50
Sample Output
【输出样例一】
9
【输出样例二】
20
9
【输出样例二】
20
HINT
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000
话说博客园这个链接有点难看。。。
换了个新环境,就学点新东西吧——数位DP
第一次做这种题还是很难搞的,%一发题解吧,没题解不能活系列
我们设f[i][j]代表i位,最高为j的数有多少是Windy数,那么我都能想到方程:f[i][j]=Sigma(f[i-1][k])(abs(k-j)>=2)
但是我们要求的是数啊,那么就得拆,拆开之后,对于每一位进行记录即可
代码如下(感觉代码讲的比我讲的清楚):
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> using namespace std; int f[20][20],a[110000]; typedef long long ll; void dp() { for(int i=0;i<=9;i++)f[1][i]=1; for(int i=2;i<=12;i++) for(int j=0;j<=9;j++) for(int k=0;k<=9;k++) if(abs(j-k)>=2) f[i][j]+=f[i-1][k]; } ll get_a(ll x) { ll len=0; while(x) { a[++len]=x%10; x/=10; } return len; } ll findans(ll len) { ll ans=0; for(int i=1;i<len;i++) for(int j=1;j<=9;j++)ans+=f[i][j]; for(int i=1;i<a[len];i++) ans+=f[len][i]; for(int i=len-1;i>=1;i--) { for(int j=0;j<a[i];j++) if(abs(a[i+1]-j)>=2)ans+=f[i][j]; if(abs(a[i+1]-a[i])<2)break; } return ans; } int main() { memset(f,0,sizeof(f)); int x,y; scanf("%d%d",&x,&y); if(x>y){int tt=x;x=y;y=tt;} dp(); ll lena=get_a(x),ansa=findans(lena); ll lenb=get_a(++y),ansb=findans(lenb); printf("%lld\n",ansb-ansa); return 0; }
by_lmy