数字游戏 区间内取模 数位DP 寒假集训

由于科协里最近真的很流行数字游戏,某人又命名了一种取模数,这种数字必须满足各位数字之和 modN 为 0。现在大家又要玩游戏了,指定一个整数闭区间 [a,b],问这个区间内有多少个取模数。

输入格式
题目有多组测试数据。每组只含三个数字 a,b,N。

输出格式
对于每个测试数据输出一行,表示各位数字和 modN 为 0 的数的个数。

样例
Input Output
1 19 9
2
数据范围与提示
对于全部数据,1≤a,b≤231−1,1≤N<100。
取模即使在当前位置上改变余数状态,板子记下来吧

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#define ls (p<<1)
#define rs (p<<1|1)
#define ll long long
using namespace std;
const int maxn = 2e6+5;
const int INF = 0x3f3f3f3f;
ll dp[30][110];//dp[pos][pre]记录了遍历第pos为位时,前一位为pre时的状态数
ll a[30],b[30];
int p;
// void init(){
    
    
//     dp[0][0]=1;
//     dp[0][1]=dp[0][2]=0;
//     for(int i=1;i<25;i++){
    
    
//         dp[i][0]=10*dp[i-1][0]-dp[i-1][1];//长度为i不含有49的个数
//         dp[i][1]=dp[i-1][0];//最高位为9但不含49的个数
//         dp[i][2]=10*dp[i-1][2]+dp[i-1][1];//含有49的个数
//     }
// }
int dfs(int pos,int pre,bool limit) {
    
    
	if(!pos){
    
    
        if(pre%p==0)
            return 1;
        else return 0;
    }	
	if(!limit&&dp[pos][pre]!=-1)	
        return dp[pos][pre];
    int up;
    if(limit)
        up=a[pos];
    else up=9;
    int ans=0;
	for(int i=0;i<=up;i++) {
    
    
		ans+=dfs(pos-1,pre+i%p,limit&&i==up);
	}
    if(!limit)
        dp[pos][pre]=ans;
	return ans;
}

int init(int n)
{
    
    
    int len=0;
    while(n){
    
    
        a[++len]=n%10;
        n/=10;
    }
    return dfs(len,0,1);
}

void solve(){
    
    
   int x,y;
   while(scanf("%d%d%d",&x,&y,&p)!=EOF){
    
    
       memset(dp,-1,sizeof(dp));
       cout<<init(y)-init(x-1)<<endl;
   }
}

int main()
{
    
    
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45891413/article/details/112909745