一道按位dp
题意: 首先定义一下B-number, 这个数是含有字串13, 并且这个数能够被13整除的数。现在给出了一个数n,n是一个小于1000000000的数。
现在要求出在小于n的数里边有多少个B-number。
思路: 这是一道明显的按位dp。 这个dp数组是这么开的。
dp[u][now][p][have],表示从上到下,上一个数为u, 当前的状态是now,当前站在第p位,have表示是否已经出现了“13”。 下面就按照一般的按位dp的步骤进行。
AC代码:
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; int dp[11][14][11][2]; int pos, num[12], n; void init() { pos = 0; while(n) { num[pos++] = n%10; n /= 10; } } int dfs(int u, int now, int p, bool have , bool istop) { if(p == -1) { if(have && now == 0) return 1; return 0; } if(!istop && dp[u][now][p][have] != -1) { return dp[u][now][p][have]; } int ans = 0, top = istop?num[p]:9; bool flag; for(int i=0; i<=top; i++) { if(u == 1 && i == 3) flag = 1; else flag = have; ans += dfs(i,(now*10+i)%13,p-1,flag,istop&&i==top); } if(!istop && dp[u][now][p][have] == -1) { dp[u][now][p][have] = ans; } return ans; } void solve() { int ans = dfs(-1,0,pos-1, 0, 1); printf("%d\n", ans); } int main() { memset(dp, -1, sizeof(dp)); while(scanf("%d", &n) != EOF) { init(); solve(); } return 0; }


浙公网安备 33010602011771号