LightOJ - 1068 Investigation(数位DP)
2015-10-28 23:07
281 查看
题目大意:给你三个数,l, r, k,问[l,r] 这个范围内,有多少个数满足该数能被k整除,且所有数位和能被k整除
解题思路:一个大剪枝,因为给的数字是小于2^31,10位数,且最高位为2,所以最大的数位和就不会超过90了,所以k超过90的,答案都是0
接下来就是数位DP了,用dp[pos][sum][mod]表示当前在i位,前面所有数位的和和k的余数是sum,前面的数和k的余数是mod
解题思路:一个大剪枝,因为给的数字是小于2^31,10位数,且最高位为2,所以最大的数位和就不会超过90了,所以k超过90的,答案都是0
接下来就是数位DP了,用dp[pos][sum][mod]表示当前在i位,前面所有数位的和和k的余数是sum,前面的数和k的余数是mod
#include <cstdio> #include <cstring> using namespace std; const int N = 10; int dp [N * 10][N * 10]; int bit ; int l, r, k, cas = 1; int dfs(int pos, int sum, int mod, int limit) { if (pos == -1) return sum == 0 && mod == 0; if (!limit && ~dp[pos][sum][mod]) return dp[pos][sum][mod]; int n = limit ? bit[pos] : 9; int ans = 0; for (int i = 0; i <= n; i++) { int s = (sum + i) % k; int t = (mod * 10 + i) % k; ans += dfs(pos - 1, s, t, limit && i == n); } if (!limit) dp[pos][sum][mod] = ans; return ans; } int DP(int x) { if (!x) return 1; int cnt = 0; while (x) { bit[cnt++] = x % 10; x /= 10; } memset(dp, -1, sizeof(dp)); return dfs(cnt - 1, 0, 0, 1); } void solve() { scanf("%d%d%d", &l, &r, &k); if (k >= 90) { printf("Case %d: %d\n", cas++, 0); return ; } printf("Case %d: %d\n", cas++, DP(r) - DP(l - 1)); } int main() { int test; scanf("%d", &test); while (test--) solve(); return 0; }
相关文章推荐
- dropzone
- USB鼠标通信协议格式
- zoj3911 线段树区间修改与求素数的结合
- js xuexi
- 第七次作业——团队作业——项目冲刺———第一天
- 黑马程序员——Java 基础:匿名内部类
- java springmvc 微信公众平台自动回复乱码问题
- Ubuntu学习 - SVN服务搭建
- 数据库(SQL Server)管理数据库表~新奇之处
- 在活动中使用Menu
- Leetcode -- Reverse Words in a String
- LightOJ - 1057 Collecting Gold(状压DP)
- 负margin的经典利用之用绝对定位来居中
- postgresql function 返回 select
- Subsets II
- 控制器的View的创建
- Unity如何将包缩小到极致
- alibaba fastjson joda time 解析器
- HTTP报文内的HTTP信息之编码提升传输速率
- java 通过userAgent获取访问者的操作系统与浏览器