HDU 3652:B-number(数位DP)
亮点:
收获:降一些时间复杂度可能带来编程复杂度。如果编程复杂度太高,而且时间允许的话,试着用一些冗余的状态来降低编程复杂度。
查询和正常DP的差别就在于:查询的时候有限制(最大不能超过那个数),而正常的时候没有
类型:数位DP
题意:找1~n内有多少能被13整除且含“13”这个子串的数。
方法:
(我的,想的比较乱的方法)
dp[i][d][mod] 表示d开头的i位数中含有“13”这个子串且%13==mod的数的个数
则:
那么下一个余数nextMod = ((mod-j*10i-1)%13+13)%13
dp[i][d][mod] =
1) d != 1: ∑dp[i-1][j=(0~9)][nextMod]
2) d == 1: ∑dp[i-1][j=(0~2,4~9)][nextMod] + ((10i-2 - nextnextMod-1/*-1去掉0*/)/13+1/*+1补上被去掉的那个*/)(接下来10i-1个数里,%13 == nextnextMod 的数。nextnextMod = ((next-3*10i-1)%13+13)%13)
但是,查询的时候,如果是1301,按照上面差的话,实际上只有1300和1301两个数,但是我们会算1300~1399这些数。 所以这里也不一样!。
唉,这种方法,d==1的情况太复杂,陷阱很多。+1-1的陷阱,然后查询的时候有陷阱。总之是一个很小心才能做出来的方法。
坑:
查询和正常DP的差别就在于:查询的时候有限制(最大不能超过那个数),而正常的时候没有。所以每一步都要小心,把查询和正常DP分开处理。这样才能对。另外,如果能更清晰一点,就不要这么写。。太容易错了。
方法二:(网上)
¨for x = 0 ~ 9
¨ if k = 1 //要求要包含13
¨ f[i,j,k,l] = f[i - 1,x,1,(l - j*10^(i-1))%13];
¨ if j = 1 and x = 3 //已经有13了。
¨ f[i,j,k,l] = f[i,j,k,l] +
¨ f[i - 1,x,0,(l - j*10^(i-1))%13];
¨ else //不要求包含13
¨ if not (j = 1 and x = 3)
¨ f[i,j,k,l] = f[i - 1,x,0,(l - j*10^(i-1))%13];
这个方法多设了一维(包含和不包含),但清晰很多~
这就是我降维降出的编程复杂度…………T T
收获:降一些时间复杂度可能带来编程复杂度。如果编程复杂度太高,而且时间允许的话,试着用一些冗余的状态来降低编程复杂度。
#include <cstdio> #include <cstring> int dp[20][10][13]; int num[20]; int n; int dfs(int i, int d, int mod, bool isQuery) { if (!isQuery && dp[i][d][mod] != -1) { return dp[i][d][mod]; } if (i == 1) { return dp[i][d][mod] = 0; } int end = isQuery?num[i-1]:9; int ans = 0; int ten = 1; for (int j = 0; j < i-1; j++) ten *= 10; int nextMod = ((mod-d*ten)%13 + 13)%13; for (int j = 0; j <= end; j++) { if (d == 1 && j == 3) { int nnxtMod = ((nextMod-(ten/10)*j)%13+13)%13; int thenum = (isQuery && j==end) ?(n%(ten/10)+1):(ten/10); int lala = thenum - nnxtMod - 1; if (lala >= 0) ans += lala/13+1; continue; } ans += dfs(i-1,j,nextMod,isQuery && j==end); } if (!isQuery) dp[i][d][mod] = ans; return ans; } int cal(int x) { int len = 0; while (x){ num[++len] = x%10; x/=10; } return dfs(len+1, 0, 0, true); } int main() { memset(dp,-1,sizeof(dp)); while (~scanf("%d", &n)) { printf("%d\n", cal(n)); } return 0; }
posted on 2014-03-11 22:01 ShineCheng 阅读(249) 评论(0) 编辑 收藏 举报