您的位置:首页 > 其它

HDU 4669 Mutiples on a circle 解题报告

2013-08-14 11:17 405 查看
题目

题意:

一串项链,每颗珠子上有一个数字,任选连续的一段,按顺时针顺序将它们的数字拼起来,若新的数字是k的倍数,则这个数字是一个 wonderful value 。求有多少个 wonderful value 。

题解:

由于K非常小,我们可以用dp[j][i]表示以第j个数结尾的所有数字中模k为i的方案为多少,那么计算dp[j+1][i]的时候乘上偏移值并加上j+1个珠子的值就行了。复杂度为nk。

注意如果读入数就去模的话,要记下原来的数的长度,比如9 和123拼起来9要乘1000,如果123先取模的话可能就乘100或者10了。就是这里卡了两个多少时……

//Time:453ms
//Memory:748KB
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 60010
using namespace std;
int num[MAXN],ten[10],len[MAXN];
int dp[2][250];
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
// freopen("/home/moor/Code/output","r",stdin);
// freopen("/home/moor/Code/o2","w",stdout);
int n,k,s,sum,tten;
long long ans;
while(scanf("%d%d",&n,&k)==2)
{
ten[0]=1;
for(int i=1;i<10;++i) ten[i]=ten[i-1]*10%k;
memset(dp,0,sizeof(dp));
sum=0;
for(int i=0;i<n;++i)
{
scanf("%d",&num[i]);
int tmp=num[i];
len[i]=0;
while(tmp) tmp/=10,++len[i];
num[i]%=k;
sum+=len[i];
}
tten=1;
for(int i=1;i<=sum;++i) tten=tten*10%k;
for(int i=0;i<n;++i) len[i]=ten[len[i]];
sum=0;
for(int i=1;i<=n;++i)
sum=(sum*len[(i==n)?0:i]%k+num[(i==n)?0:i])%k;
s=0;
for(int i=1;i<=n;++i)
{
int l=(i==n)?0:i;
++dp[s][0];
memset(dp[!s],0,sizeof(dp[!s]));
for(int j=0;j<k;++j)
if(dp[s][j])
dp[!s][(j*len[l]%k+num[l])%k]+=dp[s][j];
s=!s;
}
ans=0;
for(int i=1;i<=n;++i)
{
ans+=dp[s][0];
++dp[s][0];
if(i==n) break;
memset(dp[!s],0,sizeof(dp[!s]));
for(int j=0;j<k;++j)
if(dp[s][j])
dp[!s][(j*len[i]%k+num[i])%k]+=dp[s][j];
s=!s;
sum=(sum*len[i]%k+num[i])%k;
--dp[s][sum];
sum=(sum-tten*num[i]%k+k)%k;
}
cout<<ans<<'\n';
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: