偶尔碰到这题,简单数位DP题,然而我已生疏了……
这次算是重新想到的,看来对DP的理解有增进了……
dp[i][j][k],表示前i为,mod为j,是否出现2、3、5的剩下的数位可组成的数字。答案就是dp[len][0][0]
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define LL long long LL dp[20][7][2]; int num[20]; LL dfs(int len, int mod, bool one, int show, bool flag){ if(len == 0){ if(show == 1 && mod == 0){ dp[len][mod][show] = 1; } else dp[len][mod][show] = 0; return dp[len][mod][show]; } if(!flag && dp[len][mod][show] != -1) return dp[len][mod][show]; int up = flag ? num[len]:9; LL ans = 0, tmp = show; for(int i = 0; i <= up ; i++){ if(one && i == 8) continue; if(i == 2 || i == 3 || i == 5) tmp = (show | 1); // cout <<" tmp = " << tmp << endl; ans += dfs(len - 1, (mod * 10 + i)%7, i == 1?true:false, tmp, (flag && i == up) ? true: false); tmp = show; // printf("%I64d====%d ", ans, i); } dp[len][mod][show] = ans; return ans; } long long slove(LL n){ int len = 0; LL tmp = n; while(tmp){ num[++len] = tmp % 10; tmp /= 10; } // printf("%I64d ", n); dfs(len, 0, false, 0, true); return dp[len][0][0]; } int main(){ long long l, r; int T; scanf("%d", &T); while(T--){ memset(dp, -1, sizeof(dp)); scanf("%I64d%I64d", &l, &r); printf("%I64d ", slove(r) - slove(l - 1)); } return 0; }