HDU 3652 區間有13並且這樣整除13 的數量(數位DP)
阿新 • • 發佈:2018-11-08
題目:求1~n的範圍裡含有13且能被13整除的數字的個數。
分析:
dfs(len, num, mod, flag)
mod記錄數字對13取餘後的值
len表示當前位數
num==0 不含13且上一位不為1
pre==1 不含13且上一位為1
pre==2 含13
flag表示是否可以任意取值(判斷範圍)。
如此,記憶化搜尋即可得解。
總結:我是在最後才判斷是否可以%13 , 但是這是不可以的 , 經過這道題後,理解更好了 ;
這裡有個式子特別重要 : 關於連加取mod , 例如: 123%13=(100+20+3)%13 = ((1%13*10+2)%13*10+3)%13; !!!!! 這在數位dp很重要
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <vector> using namespace std; #define LL long long #define MOD 13 LL dp[20][3][13]; int dis[20]; LL dfs(int len, int type, int mod, bool flag) {View Codeif(len < 0) return type == 2 && mod == 0; if(!flag && dp[len][type][mod]!=-1) return dp[len][type][mod]; int end = flag?dis[len]:9; int ans = 0; for(int i=0; i<=end; i++) { if(type == 2 || (type == 1 && i == 3)) ans += dfs(len-1, 2, (mod*10+i)%MOD, flag&&i==end); else ans += dfs(len-1, i==1?1:0, (mod*10+i)%MOD, flag&&i==end); } if(!flag) dp[len][type][mod] = ans; return ans; } LL solve(LL n) { int len = 0; while(n) { dis[len++] = n%10; n /= 10; } return dfs(len-1, 0, 0, 1); } int main() { int n; memset(dp, -1, sizeof(dp)); while(cin>>n) cout<<solve(n)<<endl; return 0; }