B吉利數字
時限:1s

【題目描述】
算卦大溼biboyouyun最近得出一個神奇的結論,如果一個數字,它的各個數位相加能夠被10整除,則稱它為吉利數。現在叫你計算某個區間內有多少個吉利數字。

【輸入】
第一行為樣例個數N。接下來N行,每一行代表一個輸入樣例,每個輸入樣例有2個數,分別代表某個區間的起點a和終點b。
注意所求區間為[a,b],1<=a<=b<=10^9

【輸出】
N行。對於第x個輸入樣例,在第x行輸入該樣例所對應的結果。

【輸入樣例】
2
1 10
1 20

【輸出樣例】
0
1

【Hint】1-10之內無幸運數,1-20內只有19 這1個幸運數
------------------------------------------------------------------------------------

數位dp入門題。

一開始參考了數位dp入門ppt的非遞迴寫法,先打個表再計算,結果YY了半天還是錯了T^T

這裡有個用dfs寫法寫數位dp的模板:

http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html

程式碼:

 #include <stdio.h>
#include <string.h>
int dp[][];
int dig[]; int dfs(int i,int s,bool e)
{
if (!i) return (s==?:);
if ((!e)&&(dp[i][s]!=-)) return dp[i][s];
int res=;
int u=e?dig[i]:;
for (int q=;q<=u;q++)
res+=dfs(i-,(s+q)%,e&&q==u);
if (!e) dp[i][s]=res;
return res;
} int f(int n)
{
int len = ;
while(n)
{
dig[++len] = n % ;
n /= ;
}
return dfs(len,,true);
} int main()
{
int a,b,T;
memset(dp,-,sizeof(dp));
scanf("%d",&T);
while (T--)
{
scanf("%d %d",&a,&b);
printf("%d\n",f(b)-f(a-));
}
return ;
}

核心部分:(來自neopenx大神,orz)

 int dfs(int len,int remain,bool fp)
{
if(!len) return remain==?:;
if(!fp&&dp[len][remain]!=-)
return dp[len][remain];
int ret=,fpmax=fp?digit[len]:;
for(int i=;i<=fpmax;i++)
ret+=dfs(len-,(remain+i)%,fp&&i==fpmax);
if(!fp) dp[len][remain]=ret;
return ret;
} int f(int n)
{
int len=;
while(n)
{
digit[++len]=n%;
n/=;
}
return dfs(len,,true);
}

len:表示當前掃描到的數的位數,從高位向地位掃描

remain:表示當前狀態。如本題中表示從最高位到當前位各位數字和%10

fp:又叫first place,neopenx的大神的理解是第一次打表

該dfs函式的基本思想也是打個表記下來,邊記邊用

fpmax:當前最高位

擴充套件:hdu2089

http://blog.csdn.net/dgq8211/article/details/9296953