【BZOJ 3326】[Scoi2013]数数
题目描述
Fish 是一条生活在海里的鱼,有一天他很无聊,就开始数数玩。他数数玩的具体规则是:
-
确定数数的进制B
-
确定一个数数的区间[L, R]
-
对于[L, R] 间的每一个数,把该数视为一个字符串,列出该字符串的每一个(连续的)子串对应的B进制数的值。
-
对所有列出的数求和。现在Fish 数了一遍数,但是不确定自己的结果是否正确了。由于[L, R] 较大,他没有多余精力去验证是否正确,你能写一个程序来帮他验证吗?
输入输出格式
输入格式:
输入包含三行。
第一行仅有一个数B,表示数数的进制。
第二行有N +1 个数,第一个数为N,表示数L 在B 进制下的长度为N,接下里的N个数从高位到低位的表示数L 的具体每一位。
第三行有M+ 1 个数,第一个数为M,表示数R 在B 进制下的长度为M,接下里的M个数从高位到低位的表示数R 的具体每一位。
输出格式:
输出仅一行,即按照Fish 数数规则的结果,结果用10 进制表示,由于该数可能很大,输出该数模上20130427的模数。
输入输出样例
说明
【样例解释】
[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 }
深深地明白自己的弱小