取模数 题解
题目描述
由于科协里最近真的很流行数字游戏。
某人又命名了一种取模数,这种数字必须满足各位数字之和 \(\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;
}

浙公网安备 33010602011771号