bzoj 1026 [SCOI2009]windy数 题解

来源:互联网 发布:讲程序员的美剧 编辑:程序博客网 时间:2024/04/28 01:32

1026: [SCOI2009]windy数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 1875  Solved: 810
[Submit][Status]

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

【数据规模和约定】
20%的数据,满足 1 <= A <= B <= 1000000 。
100%的数据,满足 1 <= A <= B <= 2000000000 。

【分析】暴力显而易见时20分。对于这种题目,应该是数论或是DP。

基础的优化:A--B中的数就是1--B中的数减去1--A-1中的数。(前缀和)

【初次做】开始,我用f[i][j]表示满足条件的、长度为i且字母是j的数的个数。转移的时候方程很简单:f[i][j]+=f[i-1][k](|j-k|>=2)但是我不由地想到:这样怎么求1--X中的数呢?

【仔细思考】那么换一种角度考虑:f[i][j]表示满足条件的、长度为i且字母是j的数的个数。这样有什么好处呢?假设我们要求1--X中符合要求的数。首先设X=abcd。那么我们先加上f[4][0]、f[4][1]、f[4][2]一直到f[4][a-1],然后再加上f[3][0]、f[3][1]一直到f[3][b-1]……当然,最后是加上f[1][0]、f[1][1]一直到f[1][d]。

【注意点】

我们要开两个数组,f数组如上描述。但是因为有前导0的问题,我们还要开一个ff数组,表示ff[i][0]的状态(在f数组推导时,为了不影响后面的情况,f[i][0]的处理会少一点)。比如f[2][0]中,01、02这几种状态也是可以的。因为我们还算了0这种状态,最后函数里要减1。

②细节自己注意。

【代码】

#include<stdio.h>#include<stdlib.h>using namespace std;int f[20][10],ff[20][10],a,b,i,j,k;int p(int k){  if (k<10) return(k);  int t,ans=0,a[20],cnt=0,i,temp;  while (k>0){a[++cnt]=k%10;k/=10;}  for (i=1;i<=cnt/2;i++)   {    t=a[i];a[i]=a[cnt-i+1];a[cnt-i+1]=t;  }  for (i=0;i<a[1];i++) ans+=ff[cnt][i];int now=2;  while (now<=cnt)  {    for (i=0;i<a[now];i++)     {      if (abs(i-a[now-1])<2) continue;      ans+=f[cnt-now+1][i];    }    if (abs(a[now]-a[now-1])<2) break;    now++;    if (now>cnt)    {      now--;      temp=a[now]-a[now-1];      if (temp<0) temp=-temp;      if (temp>=2) ans+=f[1][a[now]];      break;    }  }  return ans-1;}int main(){  scanf("%ld%ld",&a,&b);  for (i=0;i<=9;i++)  {    f[1][i]=1;ff[1][i]=1;  }  for (i=2;i<=10;i++)    for (j=0;j<=9;j++)      for (k=0;k<=9;k++)        if (abs(k-j)>=2)         {          f[i][j]+=f[i-1][k];          ff[i][j]+=ff[i-1][k];        }  for (i=2;i<=10;i++)  {    ff[i][0]=0;    for (j=0;j<=9;j++)      ff[i][0]+=ff[i-1][j];  }  printf("%ld",p(b)-p(a-1));  return 0;}

1 0
原创粉丝点击