https://vjudge.net/problem/UVA-11361

菜鸡不会啊,借鉴网上的代码才知道还可以这么定义状态。

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

设dp[len][[i][j]代表长度为len各位和模k等于j,自身模k等于i时的方案,很容易就可有推出dp[i+1][(j*10+x)%k][(s+x)%k]+=dp[i][j][s];

我自己一开始写的时候只是考虑了当前位之前的答案,没考虑到当前位,最后才发现。。。。。。

这个代码比较巧妙的时在考虑当前位的时候一块就设置了初态

#include<iostream>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<stdlib.h>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<stack>
//#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int mod =1e6+7;
double esp=1e-6;
int INF =0x3f3f3f3f;
const int inf = 1<<28;
const int MAXN=1e5+10;
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=0;i<=9;i++)
//    {
//        Dp[1][i%m][i%m]++;
//    }
    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));
        }
    }

}