题意:
一串项链,每颗珠子上有一个数字,任选连续的一段,按顺时针顺序将它们的数字拼起来,若新的数字是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 ",ans); } return 0; }