lightoj 1068 - Investigation (数位DP)

要求[l, r] 区间内有多少数符合两个条件:

1)数可以整除k

2)这个数的所有位之和可以整除k

思路 : 数位dp其中一个参数存所有数位相加模k的值,另一个参数存这个当前数模k的值.

当k > 90时,因为所有位之和最大为90,所以不存在整除k的值,直接输出0.

/***********************************************
 * Author: fisty
 * Created Time: 2015-08-26 11:57:26
 * File Name   : 1068.cpp
 *********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define lson l, m, k<<1
#define rson m+1, r, k<<1|1
int t;   
int l, r, k;
#define MAX_N 12
int digit[MAX_N];
LL dp[MAX_N][MAX_N*9][MAX_N*9];
LL dfs(int len, int mod, int sum, int e){
    if(len < 0) return mod == 0 && sum == 0;
    if(!e && dp[len][mod][sum] != -1){
        return dp[len][mod][sum];
    }
    LL ans = 0;
    int d = e ? digit[len] : 9;
    for(int i = 0;i <= d; i++){
        ans += dfs(len-1, (mod * 10 + i) % k,(sum + i) % k, e && i == d);
    }
    if(!e)
        dp[len][mod][sum] = ans;
    return ans;
}
LL solve(int n){
    int len = 0;
    Memset(digit, 0);
    while(n){
        digit[len++] = n % 10;
        n /= 10;
    }
    LL ans = dfs(len-1, 0, 0, 1);
    return ans;
}
int main() {
    //freopen("in.cpp", "r", stdin);
    //cin.tie(0);
    //ios::sync_with_stdio(false);
    scanf("%d", &t);
    int cnt = 1;
    while(t--){
        Memset(dp, -1);
        scanf("%d%d%d", &l, &r, &k);
        if(k >= 90){
            printf("Case %d: 0\n", cnt++);
            continue;
        }
        printf("Case %d: %d\n",cnt++,  solve(r) - solve(l-1));
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值