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]
  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114312.html
Copyright © 2011-2022 走看看