UVA 11361 Investigating Div-Sum Property (数位DP)


题意

求区间[A, B]内能被K整除且其各位数之和也能被K整除的数。

思路

就是因为当初见了这道题不会才驱使我去学数位DP的,当时真的是一点儿思路都没有,然后看《训练指南》上的递推方法也云里雾里。现在会了数位DP后再看真是一眼题…… 设计一下按位记忆化搜索状态就好了:pos表示当前处理第几位,sum_mod表示数本身除K的余数,dig_sum表示各位数字和除K的余数。然后按位DP就好了~~~ 终于能发现记忆化搜索式的数位DP的好处了吧!!非常容易理解,也非常容易设计出状态~

代码

[cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; typedef long long LL; typedef vector <int> VI; typedef set <int> SETI; typedef queue <int> QI; typedef stack <int> SI; const int oo = 0x7fffffff; VI num; int k; int dp[15][100][100]; int dfs(int pos, int sum_mod, int dig_mod, bool limit){ if (pos == -1) return (sum_mod == 0 && dig_mod == 0); if (!limit && ~dp[pos][sum_mod][dig_mod]) return dp[pos][sum_mod][dig_mod]; int end = limit?num[pos]:9; int res = 0; for (int i = 0; i <= end; i ++){ res += dfs(pos-1, (sum_mod*10+i)%k, (dig_mod+i)%k, limit && (i==end)); } if (!limit) dp[pos][sum_mod][dig_mod] = res; return res; } int cal(int x){ num.clear(); while(x){ num.push_back(x%10); x /= 10; } MEM(dp, -1); int tmp = num.size()-1; return dfs(tmp, 0, 0, 1); } int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int t; scanf("%d", &t); while(t --){ int a, b; scanf("%d %d %d", &a, &b, &k); if (k > 100){ printf("0\n"); } else{ printf("%d\n", cal(b) - cal(a-1)); } } return 0; } [/cpp] 优质内容筛选与推荐>>
1、<4>Lua表
2、CentOS系统的优化
3、需求分析的20条法则(转载)
4、LeetCode 17. Letter Combinations of a Phone Number
5、第03组 Beta冲刺(1/4)


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号