hdu4669(递推,注意每个数位数不一定是1!!WA了许久)

题意:

一串项链,每颗珠子上有一个数字,任选连续的一段,按顺时针顺序将它们的数字拼起来,若新的数字是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了。就是这里卡了两个多少时……

//#pragma comment(linker, "/STACK:102400000")
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define pb push_back
#define mp make_pair
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 50009
using namespace std;
int m,n,T,k;
int a[N],ep,w[N],xp[10];
int num[2][209];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int ncase=0;
    while(scanf("%d%d",&n,&k)==2)
    {
        xp[0]=1;
        for(int i=1; i<10; i++)
            xp[i]=(xp[i-1]*10)%k;
        int sw=0;
        char str[10];
        memset(num,0,sizeof(num));
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            sprintf(str,"%d",a[i]);
            w[i]=strlen(str);
            sw+=w[i];
        }
        ep=1;
        for(int i=0; i<sw; i++)
            ep=(ep*10)%k;
        int cur=0,last=1,tp=0;
        for(int i=1; i<=n; i++)
        {
            memset(num[cur],0,sizeof(num[cur]));
            for(int j=0; j<k; j++)if(num[last][j])
                    num[cur][(j*xp[w[i]]+a[i])%k]+=num[last][j];
            num[cur][a[i]%k]++;
            swap(cur,last);
            tp=(tp*xp[w[i]]+a[i])%k;
        }
        LL ans=0;
        for(int i=1; i<=n; i++)
        {
            memset(num[cur],0,sizeof(num[cur]));
            for(int j=0; j<k; j++)if(num[last][j])
                    num[cur][(j*xp[w[i]]+a[i])%k]+=num[last][j];
            num[cur][a[i]%k]++;
            tp=(tp*xp[w[i]]+a[i])%k;
            num[cur][tp]--;
            ans+=num[cur][0];
            swap(cur,last);
            tp=((tp-a[i]*ep)%k+k)%k;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

posted @ 2013-09-26 16:56  baoff  阅读(224)  评论(0编辑  收藏  举报