【洛谷P2657】【BZOJ 1026】【SCOI2009】windy數

問題描述

windy定義了一種windy數。不含前導零且相鄰兩個數字之差至少爲2的正整數被稱爲windy數。spa

windy想知道, 在A和B之間,包括A和B,總共有多少個windy數?code

輸入格式

包含兩個整數,A B。blog

輸出格式

一個整數io

樣例輸入

#1class

1 10統計

 

#2數據

25 50di

樣例輸出

#1co

9數字

 

#2

20

數據範圍

100%的數據,知足 1 ≤ A ≤ B ≤ 2000000000 。

題解

數位dp。

先預處理f[i][j]表示位數爲i,最高位爲j的windy數的個數,f[i][j]=f[i-1][k](|j-k|≥2)

求小於n的wind數的個數,先統計位數小於n的位數的數中windy數的個數,f[i][j](i<len) (len爲n的位數)

對於位數和n相同的數,從高位到低位枚舉比n小的最高位

求區間[A,B]中windy數的個數,即爲小於等於B的windy數的個數減去小於A的windy數的個數,而數位dp只能求小於n的知足條件的數的個數,那麼就轉化爲小於B+1的windy數的個數減去小於A的windy數的個數

 

 1 #include <cstdio>
 2 const int p10[10]={1,10,100,1000,10000,1e5,1e6,1e7,1e8,1e9};
 3 int A,B,f[15][15],sa,sb,len,dig[15];
 4 int mabs(int x)
 5 {
 6     return x>0?x:-x;
 7 }
 8 int dp(int x)
 9 {
10     int len,pre,ans=0,y,i,j;
11     for (len=9;x<p10[len];len--);  len++; 
12     for (i=1;i<len;i++)
13       for (j=1;j<10;j++)
14         ans+=f[i][j];
15     y=x/p10[len-1];  
16     for (i=1;i<y;i++) ans+=f[len][i];
17     pre=y;  x%=p10[len-1];    
18     for (i=len-1;i>=1;i--)
19     {
20         y=x/p10[i-1];  
21         for (j=0;j<y;j++) 
22           if (mabs(j-pre)>=2)
23             ans+=f[i][j];
24         if (mabs(y-pre)<2) break;
25         pre=y; x%=p10[i-1];
26     }
27     return ans;
28 }
29 int main()
30 {
31     int i,j,k,x;
32     scanf("%d%d",&A,&B);
33     for (i=0;i<10;i++) f[1][i]=1;
34     for (i=2;i<=10;i++)
35       for (j=0;j<=9;j++)
36         for (k=0;k<=9;k++)
37           if (mabs(j-k)>=2)
38             f[i][j]+=f[i-1][k];
39     printf("%d",dp(B+1)-dp(A));
40     return 0;
41  } 
相關文章
相關標籤/搜索