【Loj #10166. 「一本通 5.3 练习 1」数字游戏】题解

题目链接

题目

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

思路

数位dp。

三个转态:当前第几位?现在这一位是否有上限?当前和模 \(N\) 是多少?

搜索是判断一下上下界,搜完后判断一下模 \(N\) 余数即可。

总结

一道挺好的数位dp练手题。

一开始我定义了五维的状态,还要存前面一个数是什么,当前首位开始了吗,后来发现不需要。

数位dp在搜索过程中尽管参数很多,但实际上要认真考虑每一个参数有没有用。

Code

// Problem: 1588:数字游戏
// Contest: SSOIER
// URL: http://ybt.ssoier.cn:8088/problem_show.php?pid=1588
// Memory Limit: 524 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
//#define N
int n, m, i, j, k; 
int f[15][2][110]; 
int a[15], x, y; 

int dfs(int n, int p, int s)
{
	if(n==0) return (s%m==0 ? 1 : 0); 
	int i, k=0; 
	if(f[n][p][s]!=-1) return f[n][p][s]; 
	for(i=0; i<=9; ++i)
	{
		if(!p && i>a[n]) break;  
		k+=dfs(n-1, p|(i<a[n]), (s+i)%m); 
	}
	return f[n][p][s]=k; 
	
}

int calc(int x)
{
	memset(f, -1, sizeof(f)); n=0; 
	while(x) a[++n]=x%10, x/=10; 
	return dfs(n, 0, 0); 
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	while(scanf("%d%d%d", &x, &y, &m)!=EOF) printf("%d\n", calc(y)-calc(x-1)); 
	return 0; 
}

posted @ 2022-01-12 14:46  zhangtingxi  阅读(181)  评论(0编辑  收藏  举报