标签:style class blog http tar ext
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4669
题意:给出一个长度为n的数字环A和数字m。问有多少子串(连续)使得这些子串的数字拼在一起是m的倍数?
思路:首先计算A[1]和A[n]不在一起的。这个简单,只要记录f[i][j]表示到第i个数字余数为j的个数即可,然后:
接着计算a[1]和a[n]在一起的情况。 我们首先预处理end[i]表示数字子串A[i,n]连在一起对m的余数。然后枚举i从[1,n-1],那么数字设数字串[1,i]的长度为L、对m的余 数为k,同时在i从1循环到i的时候f[n]将end[i]减去,那么f[n]中剩下的就是[i+1,n]这个串的所有子串[j,n]对m的余数 (i+1<=j<=n)。此时枚举[i+1,n]对m的余数j:
int a[N],b[N],p[6],n,m;
int f[2][205],end[N];
int get(int x)
{
if(x>=1&&x<=9) return 1;
if(x>=10&&x<=99) return 2;
if(x>=100&&x<=999) return 3;
return 4;
}
int pre,cur;
i64 cal1()
{
pre=0,cur=1;
int i,j,k;
FOR0(i,m) f[pre][i]=0;
f[pre][a[1]]=1;
i64 ans=0;
ans+=f[pre][0];
for(i=2;i<=n;i++)
{
FOR0(j,m) f[cur][j]=0;
f[cur][a[i]]=1;
FOR0(j,m)
{
k=(j*p[b[i]]+a[i])%m;
f[cur][k]+=f[pre][j];
}
swap(pre,cur);
ans+=f[pre][0];
}
return ans;
}
i64 cal2()
{
int i,j,k,t,temp;
i64 ans=0;
end[n]=a[n];
t=p[b[n]];
for(i=n-1;i>=1;i--)
{
end[i]=(a[i]*t+end[i+1])%m;
t=t*p[b[i]]%m;
}
t=a[1]; k=p[b[1]];
for(i=1;i<n;i++)
{
f[pre][end[i]]--;
FOR0(j,m)
{
temp=(j*k+t)%m;
if(temp==0) ans+=f[pre][j];
}
k=k*p[b[i+1]]%m;
t=(t*p[b[i+1]]+a[i+1])%m;
}
return ans;
}
int main()
{
Rush(n)
{
RD(m);
int i;
p[0]=1;
FOR1(i,4) p[i]=p[i-1]*10%m;
FOR1(i,n) RD(a[i]),b[i]=get(a[i]),a[i]%=m;
i64 ans=cal1();
ans+=cal2();
PR(ans);
}
}
HDU 4669 Mutiples on a circle(DP),布布扣,bubuko.com
HDU 4669 Mutiples on a circle(DP)
标签:style class blog http tar ext
原文地址:http://www.cnblogs.com/jianglangcaijin/p/3799508.html