HDU 3652 B-number(數位)
阿新 • • 發佈:2018-11-08
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[15]; //dp[i][j][k] //i:數位 //j:餘數 //k:3種操作狀況,0:末尾不是1, 1:末尾是1, 2:含有13 int dp[15][15][3]; int dfs(int pos, int mod, int st, int limit) { //lim記錄上限 if(pos == -1) return mod == 0 && st == 2; if(!limit && dp[pos][mod][st] != -1)//沒有上限並且已被訪問過 return dp[pos][mod][st]; int up = limit ? a[pos] : 9;//假設該位是2,下一位是3,如果現在算到該位為1,那麼下一位是能取到9的,如果該位為2,下一位只能取到3 int ans = 0; //需要在記憶化搜尋中增加一個引數mod即可,利用(a * b) % mod = (a % mod) * (b % mod)和(a + b) % mod = (a % mod) + (b % mod)來計算.比如說73 % 10 = ((7 % 10) * 10 + 3) % 10, for(int i = 0; i <= up; i++) { int mod_x = (mod * 10 + i) % 13;//難點:數學公式 if(st == 2 || (st == 1 && i == 3)) { ans += dfs(pos-1, mod_x, 2, limit && i == up); } else if(i == 1) { ans += dfs(pos-1, mod_x, 1, limit && i == up); } else { ans += dfs(pos-1, mod_x, 0, limit && i == up); } } if(!limit) dp[pos][mod][st] = ans; return ans; } int main() { int n, len; while(~scanf("%d", &n)) { memset(a, 0, sizeof(a)); memset(dp, -1, sizeof(dp)); len = 0; while(n) { a[len++] = n%10; n /= 10; } printf("%d\n", dfs(len-1, 0, 0, 1)); } return 0; }