• HDU 4389 X mod f(x) (数位dp)


      终于把这题搞出来了。。。前后看了半一星期。比赛堆积的题目在减少。。。加油!

      数位dp,f[i][sum][mod][res]表示前i位,和为sum,模为mod,sum%mod结果为res的状态个数。f[i+1][sum+k][mod][(res*10 + k)%mod] += f[i][sum][mod][res];

    予处理出所有的f[i][sum][mod][res], 然后从高到低逐位统计。比如当前位为a_i,则枚举当前位为0...(a_i-1) 这些数,i位往后的数的所有状态已经预处理出来了。。。所以出现 %mod == 0的情况直接累加就可以。。。最后单独处理一下最低位。。。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <vector>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <string>
      8 #include <set>
      9 #include <ctime>
     10 #include <queue>
     11 #include <map>
     12 #include <functional>
     13 #include <numeric>
     14 #include <sstream>
     15 
     16 #define CL(arr, val)    memset(arr, val, sizeof(arr))
     17 #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
     18 #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
     19 #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
     20 #define L(x)    (x) << 1
     21 #define R(x)    (x) << 1 | 1
     22 #define MID(l, r)   (l + r) >> 1
     23 #define Min(x, y)   x < y ? x : y
     24 #define Max(x, y)   x < y ? y : x
     25 #define E(x)    (1 << (x))
     26 
     27 const int eps = 1e-4;
     28 typedef long long LL;
     29 const int inf = ~0u>>2;
     30 using namespace std;
     31 
     32 const int N = 83;
     33 
     34 int f[12][N][N][N];
     35 int ten[15];
     36 
     37 
     38 void init() {
     39     int i, sum, mod, res, k, j;
     40     ten[0] = 1;
     41     for(i = 1; i <= 10; ++i)    ten[i] = ten[i-1]*10;
     42     CL(f, 0);
     43     for(i = 0; i < 10; ++i) {
     44         for(j = 1; j < N; ++j)  f[1][i][j][i%j] = 1;
     45     }
     46 
     47     for(i = 1; i < 9; ++i) {
     48         for(sum = 0; sum < N; ++sum) {
     49             for(mod = 1; mod < N; ++mod) {
     50                 for(res = 0; res < N; ++res) {
     51                     if(!f[i][sum][mod][res])    continue;
     52                     for(k = 0; k < 10 && sum + k < N; ++k)
     53                         f[i+1][sum + k][mod][(res*10 + k)%mod] += f[i][sum][mod][res];
     54                 }
     55             }
     56         }
     57     }
     58 }
     59 
     60 int a[15];
     61 
     62 int Do(int x) {
     63     if(x <= 10) return x;
     64     int tsum = 0, i, j, n = 0, u;
     65     int mod, sum, num, res, ans = 0;
     66 
     67     for(u = x ; u > 0; u /= 10)  a[++n] = u%10, tsum += u%10;
     68 
     69     for(mod = 1; mod <= 9*n; ++mod) {    //枚举取模,也就是所有数位的和
     70         if(mod > x) break;
     71         sum = mod;
     72         num = 0;
     73         for(i = n; i > 1; --i) {
     74             for(j = 0; j < a[i] && j <= sum; ++j) {    //从0...(a_i - 1)枚举。第i位的数
     75                 for(res = 0; res < mod; ++res) {    //res 表示i位以后的数位和取模得到的值
     76                     if((num + j*ten[i-1] + res)%mod == 0) {    //根据同余公式
     77                         ans += f[i-1][sum - j][mod][res];
     78                     }
     79                 }
     80             }
     81             sum -= a[i];
     82             num += a[i]*ten[i-1];
     83         }
     84     }
     85     while(1) {    //单独处理最低位
     86         if(x%tsum == 0) ans++;
     87         if(x%10 == 0)   break;
     88         x -- ; tsum --;
     89     }
     90     return ans;
     91 }
     92 
     93 int main() {
     94     freopen("data.in", "r", stdin);
     95 
     96     init();
     97     int t, a, b, cas = 0;
     98     scanf("%d", &t);
     99     while(t--) {
    100         scanf("%d%d", &a, &b);
    101         printf("Case %d: %d\n", ++cas, Do(b) - Do(a - 1));
    102     }
    103     return 0;
    104 }
  • 相关阅读:
    Oracle 行列转换
    Oracle中特殊的INSERT语句
    在.net中实现压缩多个文件为.zip文件 【转】
    JavaScript 原型链【转】
    Oracle安装中的DHCP问题
    每日一题力扣49
    每日一题力扣423
    每日一题力扣451
    每日一题力扣237
    每日一题力扣383
  • 原文地址:https://www.cnblogs.com/vongang/p/2659858.html
Copyright © 2020-2023  润新知