【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;
}
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/15792601.html