P2657 [SCOI2009]windy数

Posted xiaoyezi-wink

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2657 [SCOI2009]windy数相关的知识,希望对你有一定的参考价值。

P2657 [SCOI2009]windy数

题解

数位DP板子题

f[ i ][ j ] 表示长度为 i 的数字,最高温填的数字是  j  的时候,windy数的个数

f[ i ][ j ] = Σ f[ i ][ k ] ( abs(k-j)>=2 )

 

代码

#include<bits/stdc++.h>

using namespace std;

inline int read()

    int ans=0;
    char last= ,ch=getchar();
    while(ch<0||ch>9) last=ch,ch=getchar();
    while(ch>=0&&ch<=9) ans=ans*10+ch-0,ch=getchar();
    if(last==-) ans=-ans;
    return ans;


int aa,bb;
int f[11][10];
//f[i][j] 从后往前数第i位填了数字j的windy数个数
//或者可以理解为长度为i的数字,最高位填了数字j的windy数个数 

void pre()   //预处理 

    for(int i=0;i<=9;i++) f[1][i]=1;
    //单数位的数字也是windy数 
    
    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)
              f[i][j]+=f[i-1][k];


int work(int x)  //1~x-1中有多少个windy数 

    int ans=0;
    int a[11],len=0;
    while(x)  //存下x的各位数字 
    
        a[++len]=x%10;
        x/=10;
    
    
    for(int i=1;i<len;i++)
      for(int j=1;j<=9;j++)
        ans+=f[i][j];
    //长度比x小的数字一定是合法的 
    
    for(int i=1;i<=a[len]-1;i++)
        ans+=f[len][i];  
    //最高位数字比x最高位小的也一定合法 
    
    for(int i=len-1;i>=1;i--)  //从高位向低位枚举 
    
        for(int j=0;j<=a[i]-1;j++) //x是上界,不可以超过x ,j是第i位上的数字 
           if(abs(j-a[i+1])>=2) ans+=f[i][j]; //和上一位比较,合法 
        if(abs(a[i+1]-a[i])<2) break; //上一位和自己比较,不合法,直接退出for循环 
    
    
    return ans;  


int main()

    aa=read();bb=read();
    pre();
    printf("%d",work(bb+1)-work(aa));
    return 0;

 

以上是关于P2657 [SCOI2009]windy数的主要内容,如果未能解决你的问题,请参考以下文章

P2657 [SCOI2009]windy数

P2657 [SCOI2009]windy数

P2657 [SCOI2009]windy数 题解

P2657 [SCOI2009] windy 数

P2657 [SCOI2009]windy数

Luogu P2657 [SCOI2009]windy数