【UVA11361】Investigating Div-Sum Property——数位DP

来源:互联网 发布:淘宝怎么买爱奇艺会员 编辑:程序博客网 时间:2024/05/17 23:02

An integer is divisible by 3 if the sum of its digits is also divisible by 3. For example, 3702 is divisible
by 3 and 12(3+7+0+2) is also divisible by 3. This property also holds for the integer 9.
In this problem, we will investigate this property for other integers.

Input

The first line of input is an integer T (T < 100) that indicates the number of test cases. Each case is
a line containing 3 positive integers A, B and K. 1 ≤ A≤ B < 231 and 0 < K < 10000.

Output

For each case, output the number of integers in the range [A, B] which is divisible by K and the sum
of its digits is also divisible by K.

Sample Input

3
1 20 1
1 20 2
1 1000 4

Sample Output

20
5
64

题意:计算区间[A,B]kk

分析:数位Dp的入门题,一般数位Dp[x]表示在不超过x的数中满足条件的输的个数,那么本题的答案就是Dp[B] -Dp[A-1],现在的任务就是如何求出Dp[x],假设x = 3234,那么我们可以将x分解一下求[0,999],[1000,1999],[2000,2999],[3000,3099],[3100,3199],[3200,3209],[3210,3219],[3220,3229],[3230,3231],[3231,3232],[3232,3233],[3233,3234]。由于各区间之间是相互独立的,满足加法定理,所以我们Dp[i][j][s],表示i位时,对k取余为j,各位数之和对k取余为s的数量,所以可以枚举第i+1上的数x则Dp[i+1][(j*10+x)%k][(s+x)%k]+=Dp[i][j][s],对于区间我们从高位到低位枚举,处理区间的限制。

#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <stack>#include <string>#include <algorithm>#include <iostream>using namespace std;typedef long long LL;LL Dp[11][110][110];int Po[11];void Break(LL n){    Po[0] = 0;    stack<int>ST;    while(n)    {        ST.push(n%10);        n /= 10;    }    while(!ST.empty())    {        Po[++Po[0]] = ST.top();        ST.pop();    }}LL Opera(LL n , LL m){    memset(Dp,0,sizeof(Dp));    Break(n);    LL ans =0 ,ant = 0;    for(int i = 1;i<=Po[0];i++)    {        for(int j = 0;j<m;j++)        {            for(int k = 0;k<m;k++)            {                for(int s = 0;s<=9;s++)                {                    Dp[i][(j+s)%m][(k*10+s)%m]+=Dp[i-1][j][k];                }            }        }        for(int j = 0;j<Po[i];j++)        {            Dp[i][(ans+j)%m][(ant*10+j)%m]++;        }        ans = (ans+Po[i])%m;        ant = (ant*10+Po[i])%m;    }    if(ans==0&&ant==0)    {        Dp[Po[0]][0][0]++;    }    return Dp[Po[0]][0][0];}int main(){    LL n,m,k;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%lld %lld %lld",&n,&m,&k);        if(k>=100)        {            printf("0\n");        }        else        {            printf("%lld\n",Opera(m,k)-Opera(n-1,k));        }    }}
0 0
原创粉丝点击