数字游戏 数位DP
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数字游戏 数位DP相关的知识,希望对你有一定的参考价值。
题目:
由于科协里最近真的很流行数字游戏,某人又命名了一种取模数,这种数字必须满足各位数字之和 m o d N mod\\ N mod N 为 0 0 0。现在大家又要玩游戏了,指定一个整数闭区间 [ a , b ] [a,b] [a,b],问这个区间内有多少个取模数。
思路:
- 状态表示:
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]代表共i
位,最高位为j
,且每个位的数之和模N余数为k的数的个数 - 状态转移:
f [ i ] [ j ] [ k ] = ∑ x = 0 9 f [ i − 1 ] [ x ] [ m o d ( k − j , p ) ] f[i][j][k] = \\sum _{x=0}^{9}f[i-1][x][mod(k-j,p)] f[i][j][k]=∑x=09f[i−1][x][mod(k−j,p)],因为少了一位,所以最高位是随便的
last
记录之前访问的位上数的和
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 35;
int p;
int f[N][10][105];
int mod(int a,int b)
{
return (a%b+b)%b;
}
void init()
{
memset(f,0,sizeof f);
for(int i=0;i<=9;i++) f[1][i][i%p]=1;
for(int i=2;i<N;i++)
for(int j=0;j<=9;j++)
for(int k=0;k<p;k++)
for(int x=0;x<=9;x++)
f[i][j][k] += f[i-1][x][mod(k-j,p)];
}
int dp(int n)
{
if(!n) return 1;
vector<int>nums;
while(n) nums.push_back(n%10),n/=10;
int last = 0;
int res = 0;
for(int i=nums.size()-1;i>=0;i--)
{
int x = nums[i];
for(int j=0;j<x;j++)
res += f[i+1][j][mod(-last,p)];
last += x;
if(!i && last%p==0) res ++;//访问到最后一位时,且满足所有位的数的和模p余0,加上本身这个数
}
return res ;
}
int main()
{
int l,r;
while(cin>>l>>r>>p)
{
init();
cout<<dp(r)-dp(l-1)<<'\\n';
}
return 0;
}
以上是关于数字游戏 数位DP的主要内容,如果未能解决你的问题,请参考以下文章