【BZOJ 3326】[Scoi2013]数数

题目描述

Fish 是一条生活在海里的鱼,有一天他很无聊,就开始数数玩。他数数玩的具体规则是:

  1. 确定数数的进制B

  2. 确定一个数数的区间[L, R]

  3. 对于[L, R] 间的每一个数,把该数视为一个字符串,列出该字符串的每一个(连续的)子串对应的B进制数的值。

  4. 对所有列出的数求和。现在Fish 数了一遍数,但是不确定自己的结果是否正确了。由于[L, R] 较大,他没有多余精力去验证是否正确,你能写一个程序来帮他验证吗?

输入输出格式

输入格式:

 

输入包含三行。

第一行仅有一个数B,表示数数的进制。

第二行有N +1 个数,第一个数为N,表示数L 在B 进制下的长度为N,接下里的N个数从高位到低位的表示数L 的具体每一位。

第三行有M+ 1 个数,第一个数为M,表示数R 在B 进制下的长度为M,接下里的M个数从高位到低位的表示数R 的具体每一位。

 

输出格式:

 

输出仅一行,即按照Fish 数数规则的结果,结果用10 进制表示,由于该数可能很大,输出该数模上20130427的模数。

 

输入输出样例

输入样例#1: 复制
10
3 1 0 3
3 1 0 3
输出样例#1: 复制
120

说明

【样例解释】

[103, 103] 之间仅有数103,该数的所有子串包括1, 10, 103, 0, 03, 3,其和为120。

【数据范围与约定】

20% 数据,0 <= R <= L <= 10^5。

50% 数据,2 <= B <= 1000,1 <= N,M <= 1000。

100% 数据,2 <= B <= 10^5,1 <= N,M <= 10^5。

题解

  我不会

  题解的思路明白,但代码根本看不懂

  米娜自己去看好了……我实在无能为力……

  这里

 1 //minamoto
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<iostream>
 6 #define ll long long
 7 using namespace std;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 inline int read(){
11     #define num ch-'0'
12     char ch;bool flag=0;int res;
13     while(!isdigit(ch=getc()))
14     (ch=='-')&&(flag=true);
15     for(res=num;isdigit(ch=getc());res=res*10+num);
16     (flag)&&(res=-res);
17     #undef num
18     return res;
19 }
20 const int N=100005,mod=20130427;
21 int n,m,B,L[N],R[N];
22 ll SB[N],S[N],a[N][2],s[N][2],ss[N][2],sl[N][2];
23 int solve(int *p,int l){
24     memset(a,0,sizeof(a));
25     memset(s,0,sizeof(s));
26     memset(ss,0,sizeof(ss));
27     memset(sl,0,sizeof(sl));
28     a[l][0]=1;
29     for(int i=l-1;~i;--i){
30         int c=(i==l-1?0:B);
31         a[i][0]=a[i+1][0];
32         a[i][1]=(c-1+a[i+1][1]*B+a[i+1][0]*p[i])%mod;
33         sl[i][0]=sl[i+1][0]+a[i+1][0];
34         sl[i][1]=(c-1+sl[i][0]*p[i]+
35                     (sl[i+1][1]+a[i+1][1])*B)%mod;
36         ss[i][0]=(ss[i+1][0]*B+p[i]*sl[i][0])%mod;
37         ss[i][1]=(S[c]+ss[i+1][0]*B*p[i]+S[p[i]]*sl[i][0]+
38                     ss[i+1][1]*B%mod*B+
39                     S[B]*(sl[i+1][1]+a[i+1][1]))%mod;
40         s[i][0]=(s[i+1][0]+ss[i][0])%mod;
41         s[i][1]=(s[i+1][0]*p[i]+s[i+1][1]*B+ss[i][1])%mod;
42     }
43     return (s[0][0]+s[0][1])%mod;
44 }
45 int main(){
46     //freopen("testdata.in","r",stdin);
47     B=read();SB[0]=1;
48     for(int i=0;i<N-1;++i) SB[i+1]=(SB[i]*B+1)%mod;
49     S[0]=0;
50     for(int i=0;i<B;++i) S[i+1]=(S[i]+i)%mod;
51     n=read();
52     for(int i=0;i<n;++i) L[n-i-1]=read();
53     for(int i=0;i<n;++i){
54         if(L[i]>0){--L[i];break;}
55         L[i]=B-1;
56     }
57     if(!L[n-1]) --n;
58     m=read();
59     for(int i=0;i<m;++i) R[m-i-1]=read();
60     printf("%d\n",(solve(R,m)-solve(L,n)+mod)%mod);
61     return 0;
62 }

 

posted @ 2018-08-27 11:34  bztMinamoto  阅读(295)  评论(0编辑  收藏  举报
Live2D