取模数 题解

题目描述

由于科协里最近真的很流行数字游戏。

某人又命名了一种取模数,这种数字必须满足各位数字之和 \(\mod n\)\(0\)

现在大家又要玩游戏了,指定一个整数闭区间 \([a,b]\),问这个区间内有多少个取模数。

分析

数位 dp。

\(dp_{i,j,k}\) 表示当前处理到第 \(i\) 位,已处理的各位数字之和 \(\mod n\)\(j\),且当前是否受到上限约束的方案数。

对于当前位,枚举所有可能的数字,更新数字和 \(\mod n\) 的值。

Windy 数 不一样的是,本题不需要判断前导 \(0\)。本题只关心数字和,而前导 \(0\) 对数字和是没有任何贡献的,故不需要判断。

// 记忆化搜索
#include<bits/stdc++.h>
using namespace std;
int mo,dp[10][107][2],mx[10];
int dfs(int i,int j,int pd1)
{
    if(i==-1) return (j%mo==0)?1:0;
    if(!pd1&&dp[i][j][pd1]!=-1) return dp[i][j][pd1];
    int sum=0,up=pd1?mx[i]:9;
    for(int k=0;k<=up;k++)
	{
    	int d=(j+k)%mo;
        sum+=dfs(i-1,d,pd1&&(k==up));
    }
    if(!pd1) dp[i][j][pd1]=sum;
    return sum;
}
int solve(int n)
{
	int x=0;
	while(n)
	{
		mx[x++]=n%10;
		n/=10;
	}
	memset(dp,-1,sizeof(dp));
	return dfs(x-1,0,1);
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); 
    int a,b;
    while(cin>>a>>b>>mo) 
		cout<<solve(b)-solve(a-1)<<'\n'; // 转换问题
    return 0;
}
posted @ 2025-09-06 11:34  Aron_2023  阅读(4)  评论(0)    收藏  举报