zoukankan      html  css  js  c++  java
  • 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 "); } else{ printf("%d ", cal(b) - cal(a-1)); } } return 0; } [/cpp]
  • 相关阅读:
    ECS内网穿透
    设置服务器ssh会话时间
    VScode插件
    Linux拷贝U盘文件(命令行)
    打开IDM下载视频时弹出防火墙阻止下载,解决方案
    如何将jmeter.bat命令文件固定到任务栏
    jmeter安装教程
    安装JDK8.0(JDK1.8) & 环境变量配置 & idea中配置java路径
    教你不用任何第三方软件实现任务栏居中
    [Unity优化]gc03:代码优化
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114097.html
Copyright © 2011-2022 走看看