HDU 4669 Mutiples on a circle 数位DP

时间:2023-03-10 02:58:33
HDU 4669 Mutiples on a circle 数位DP

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4669

考察对取模的的理解深不深刻啊,当然还有状态的设计····设d[i][j]表示以第i个数结尾,余数为j的取法数,那么在第i个数后加一个数

那么有递推式int yu =(  j *  log10( a[i+1] ) + a[i+1] )%k,

d[i+1][yu] += d[i][j] .考虑到这是一个环这样多生成了一个余数,这个余数应该减去,还有++d[i+1][a[i+1]%k].

贴代码:

 #include <cstdio>
#include <cmath>
#include <cstring>
#define N1 50005
#define N2 205
int dp[N1][N2];
int a[N1],b[N1],e[N1*];
int solve(int n,int k)
{
e[]=;
for(int i=; i<=n*; ++i)//e[i]存的是10^i%k
e[i] = e[i-]*%k;
for(int i=; i<n; ++i)//初始化dp为0
for(int j=; j<k; ++j)
dp[i][j] =;
for(int i=; i<=n; ++i)
{
scanf("%d",&a[i]);
b[i] = log10(a[i])+;//b[i]存的是每一个数有多少位
}
int s =;
int len=;// 预处理出以第n个数结尾,余数为j取法数
for(int i=n; i > ; --i)
{
s = (a[i]*e[len]+s)%k;
++dp[][s];
len += b[i];
}
int ans= dp[][];
for(int i=; i<n; ++i)
{
for(int j=; j<k; ++j)
dp[i][(j*e[b[i]]+a[i])%k] += dp[i-][j];
s = (s*e[b[i]]+a[i])%k;//这是一个不合法的余数
//如9 6 4 2 8 (9 6 4 2 8)这个余数是964289%k
--dp[i][s];
++dp[i][a[i]%k];//独立的
s = ((s-a[i]*e[len])%k+k)%k;
//计算64289的余数,因为(9*10^len + 64289)%k = s
//那么64289%k = ((s-a[i]*e[len])%k+k)%k;
ans += dp[i][];
}
return ans;
}
int main()
{
// freopen("1004.txt","r",stdin);
int n,k;
while(scanf("%d%d",&n,&k) != EOF)
{
printf("%d\n",solve(n,k));
}
return ;
}