步驟:
1.init()預處理出dp數組.dp[i][j]表示數位長度爲i的最高爲j的數字中的windy數的個數.則dp[i][j]=sum(dp[i-1][k]),0<=k<=9&&abs(k-j)>=2
2.寫出計算[1,x]的windy數個數的函數cal(int x).
假設x爲2345,則先算出[1,1000),再算[1000,2000),再算[2000,2300),[2300,2340),[2340,2345),2345.
3.求[a,b]的windy數,就是求cal(b)-cal(a-1).
主要代碼:
public class Main {
static int dp[][]=new int[20][10];
//dp[i][j]存儲位數爲i的最高位爲j的數字中的windy數。則dp[i][j]=sum(dp[i-1][k]),9>=k>=0,|k-j|>=2
static void init() {//預處理出dp數組
for(int i=0;i<=9;i++) {
dp[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(Math.abs(j-k)>=2) {
dp[i][j]+=dp[i-1][k];
}
}
}
}
}
static int cal(int x) {//計算[0,x]之間的windy數
int res=0;
int s[]=new int[20];
int len=0;
//特判,如果x=0
if(x==0) {
return 0;
}
while(x>0) {
s[++len]=x%10;
x/=10;
}
//例如x=2345,先算出[1,1000)的windy數
for(int i=1;i<len;i++) {
for(int j=1;j<=9;j++) {
res+=dp[i][j];
}
}
//計算[1000,2000)的
for(int i=1;i<s[len];i++) {
res+=dp[len][i];
}
//計算[2000,2345]的
for(int i=len-1;i>=1;i--) {
for(int j=0;j<s[i];j++) {
if(Math.abs(j-s[i+1])>=2) {
res+=dp[i][j];
}
}
//判斷2345是不是windy數
if(i==1&&Math.abs(s[i]-s[i+1])>=2) {
res+=1;
}
//如果當前位與高一位相差不超過2,直接break;
if(Math.abs(s[i]-s[i+1])<2) {
break;
}
}
return res;
}
public static void main(String args[]) {
InputReader sc=new InputReader(System.in);
PrintWriter out=new PrintWriter(System.out);
int a,b;
a=sc.nextInt();
b=sc.nextInt();
init();
int res=cal(b)-cal(a-1);
out.println(res);
out.flush();
out.close();
}
}