题目链接:HDU3652
【题意】求1~n之间有多少个数字包含13且能被13整除。
【分析】总算自己能想出数位DP了,我求的是不满足情况的数量,然后答案减一下就好了,用dp[len][mod][is1][ok]表示len位的数字中除以13的余数为mod,上一位是否为1,是否包含13的数字有几个,套下数位DP模版就好了,注意如果包含了13不能不往下递归,可能还有一个条件(mod%13!=0)也需要计数,所以加了一个ok状态看是否包含13,最后在判断不满足条件的数( ((bool)mod) || ok );
【AC CODE】0ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 11; int dp[MAXN][13][2][2], bit[MAXN]; int dfs(int len, int mod, bool is1, bool ok, bool ismax)//0~n不满足"包含13并且能被13整除"的数量 { if(!len) return ((bool)mod) || ok; if(!ismax && ~dp[len][mod][is1][ok]) return dp[len][mod][is1][ok]; int mx = ismax?bit[len]:9, sum = 0; repe(i,0,mx) { if(is1 && 3 == i) sum += dfs(len-1,(mod*10+i)%13,1 == i,0,ismax&&i==mx); else sum += dfs(len-1,(mod*10+i)%13,1 == i,ok,ismax&&i==mx); } return ismax?sum:dp[len][mod][is1][ok] = sum; } int sloved(int n) { int len = 0; while(n) { bit[++len] = n%10; n /= 10; } return dfs(len,0,0,1,1); } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int n; clc(dp,-1); while(~scanf("%d", &n)) { printf("%d\n", n-sloved(n)+1); } return 0; }
当然是也可以正着来,dp表示符合条件的个数。
【AC CODE】0ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 11; int dp[MAXN][13][2][2], bit[MAXN]; int dfs(int len, int mod, bool is1, bool ok, bool ismax) { if(!len) return !mod && ok; if(!ismax && ~dp[len][mod][is1][ok]) return dp[len][mod][is1][ok]; int mx = ismax?bit[len]:9, sum = 0; repe(i,0,mx) { if(is1 && 3 == i) sum += dfs(len-1,(mod*10+i)%13,1 == i,1,ismax&&i==mx); else sum += dfs(len-1,(mod*10+i)%13,1 == i,ok,ismax&&i==mx); } return ismax?sum:dp[len][mod][is1][ok] = sum; } int sloved(int n) { int len = 0; while(n) { bit[++len] = n%10; n /= 10; } return dfs(len,0,0,0,1); } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int n; clc(dp,-1); while(~scanf("%d", &n)) { printf("%d\n", sloved(n)); } return 0; }