题意:
给出一个进制BBB,一个BBB进制下的区间[L,R][L,R][L,R],定义f(iB)f(i_{B})f(iB)为iii的十进制的数i10i_{10}i10的所有子串形成的新数字的总和,例如f(1010)=1+0+10=11f(10_{10})=1+0+10=11f(1010)=1+0+10=11,求∑iB=LRf(i)\sum_{i_{B}=L}^{R}f(i)∑iB=LRf(i)
Solution:
一个非常麻烦的数位dpdpdp,按照数位dpdpdp的一般套路,都是计算[0,r]−[0,l−1][0,r]-[0,l-1][0,r]−[0,l−1]
按照数位dpdpdp的方法,不妨先考虑加入一个数新产生的贡献是多少?
设AAA是一个数,BBB是一个数,ABABAB在下面都表示为首尾拼接的数,例如A=10,B=35A=10,B=35A=10,B=35,则AB=1035AB=1035AB=1035,并且约定说数位的第几位是从低权位开始数的,比如123412341234的第3位是2
设fsxf_{sx}fsx为拼接数sxsxsx的贡献,并且xxx为单数码数,给sss拼接上xxx,产生的贡献应该是所有新的后缀代表的数的和,新的后缀是在原来后缀的基础上形成的,于是有
fsx=B×fs+x×(ls+1) f_{sx}=B\times f_{s}+x\times (l_{s}+1) fsx=B×fs+x×(ls+1)
其中lsl_{s}ls是其中一个sss数的长度,按照数位dpdpdp的思路,在iii位放置xxx,他能产生作用的是前面所能形成的所有数,于是
fsx=B×fs+x×(totlens+tots) f_{sx}=B\times f_{s}+x\times (totlen_{s}+tot_{s}) fsx=B×fs+x×(totlens+tots)
其中totlenstotlen_{s}totlens是可以是sss的所有数的长度和,totstot_{s}tots是可以是sss的数的后缀数量和,同时按照数位dpdpdp,我们将是否卡上界分开考虑,设f[i][0]f[i][0]f[i][0]是放置了第iii位,前iii位不卡上界的贡献,f[i][1]f[i][1]f[i][1]则是卡上界的贡献,接下来的dpdpdp数组皆是如此,并且dpdpdp放置数码顺序时从高权位向低权位放置。接下来的sxsxsx为拼接数方式说明,在i+1i+1i+1基础上讨论iii就等价于sss基础上拼接xxx
于是
f[i][0]=∑x=0B−1(B×f[i+1][0]+x×(totlen[i+1][0]+tot[i+1][0]+1))+∑x=0nums[i]−1(B×f[i+1][1]+x×(totlen[i+1][1]+tot[i+1][1])) f[i][0]=\sum_{x=0}^{B-1}(B\times f[i+1][0]+x\times(totlen[i+1][0]+tot[i+1][0]+1))+\sum_{x=0}^{nums[i]-1}(B\times f[i+1][1]+x\times (totlen[i+1][1]+tot[i+1][1])) f[i][0]=x=0∑B−1(B×f[i+1][0]+x×(totlen[i+1][0]+tot[i+1][0]+1))+x=0∑nums[i]−1(B×f[i+1][1]+x×(totlen[i+1][1]+tot[i+1][1]))
f[i][1]=∑x=nums[i]nums[i](B×f[i+1][1]+x×(totlen[i+1][1]+tot[i+1][1])) f[i][1]=\sum_{x=nums[i]}^{nums[i]}(B\times f[i+1][1]+x\times (totlen[i+1][1]+tot[i+1][1])) f[i][1]=x=nums[i]∑nums[i](B×f[i+1][1]+x×(totlen[i+1][1]+tot[i+1][1]))
其中f[i][0]f[i][0]f[i][0]的第一个求和中最后一项的最后一项+1的缘故是,需要考虑当前位置放置第一个非0数码,前面放置前导0的情况,此时对于每个xxx都贡献一个xxx的量,之后化简可得
f[i][0]=B2×f[i+1][0]+B×(B−1)2×(totlen[i+1][0]+tot[i+1][0]+1)+B×nums[i]×f[i+1][1]+nums[i]×(nums[i]−1)2×(totlen[i+1][1]+tot[i+1][1]) f[i][0]=B^{2}\times f[i+1][0]+\frac{B\times(B-1)}{2}\times(totlen[i+1][0]+tot[i+1][0]+1)+B\times nums[i]\times f[i+1][1]+\frac{nums[i]\times(nums[i]-1)}{2}\times(totlen[i+1][1]+tot[i+1][1]) f[i][0]=B2×f[i+1][0]+2B×(B−1)×(totlen[i+1][0]+tot[i+1][0]+1)+B×nums[i]×f[i+1][1]+2nums[i]×(nums[i]−1)×(totlen[i+1][1]+tot[i+1][1])
f[i][1]=B×f[i+1][1]+nums[i]×(totlen[i+1][1]+tot[i+1][1]) f[i][1]=B\times f[i+1][1]+nums[i]\times (totlen[i+1][1]+tot[i+1][1]) f[i][1]=B×f[i+1][1]+nums[i]×(totlen[i+1][1]+tot[i+1][1])
我们接着考虑如何转移tottottot与totlentotlentotlen
拼接之后的tottottot是在原有的后缀数量得到的,每个后缀与一个xxx新生成一个,同时,当我们不卡上界时,我们可以在当前位置放置第一个非0数码,前面所有放置位置为前导0,即
tot[i][0]=∑x=0B−1tot[i+1][0]+∑x=0nums[i]−1tot[i+1][1]+B−1 tot[i][0]=\sum_{x=0}^{B-1}tot[i+1][0]+\sum_{x=0}^{nums[i]-1}tot[i+1][1]+B-1 tot[i][0]=x=0∑B−1tot[i+1][0]+x=0∑nums[i]−1tot[i+1][1]+B−1
tot[i][1]=∑x=nums[i]nums[i]tot[i+1][1]=tot[i+1][1] tot[i][1]=\sum_{x=nums[i]}^{nums[i]}tot[i+1][1]=tot[i+1][1] tot[i][1]=x=nums[i]∑nums[i]tot[i+1][1]=tot[i+1][1]
其中,在当前位置放置第一个非0数码的情形本来是BBB种,但是由于此时计算不卡上界,所以需要-1
totlentotlentotlen同样是在原来的后缀总长度上得到的,每个后缀与一个xxx拼接,长度+1。每个xxx能与tot[i+1][0/1]tot[i+1][0/1]tot[i+1][0/1]个后缀拼接,这tot[i+1][0/1]tot[i+1][0/1]tot[i+1][0/1]个后缀的总长度为totlen[i+1][0/1]totlen[i+1][0/1]totlen[i+1][0/1],于是
totlen[i][0]=∑x=0B−1(totlen[i+1][0]+tot[i+1][0])+∑x=0nums[i]−1(totlen[i+1][1]+tot[i+1][0]+B−1) totlen[i][0]=\sum_{x=0}^{B-1}(totlen[i+1][0]+tot[i+1][0])+\sum_{x=0}^{nums[i]-1}(totlen[i+1][1]+tot[i+1][0]+B-1) totlen[i][0]=x=0∑B−1(totlen[i+1][0]+tot[i+1][0])+x=0∑nums[i]−1(totlen[i+1][1]+tot[i+1][0]+B−1)
totlen[i][1]=∑x=nums[i]nums[i](totlen[i+1]+tot[i+1][1]) totlen[i][1]=\sum_{x=nums[i]}^{nums[i]}(totlen[i+1]+tot[i+1][1]) totlen[i][1]=x=nums[i]∑nums[i](totlen[i+1]+tot[i+1][1])
其中B−1B-1B−1的解释是与tottottot转移的是一样的,这里就不计算化简了。
最后如何统计答案
设gsxg_{sx}gsx为拼接数sxsxsx的答案,显然他的答案包括两部分,前面的答案gsg_{s}gs与拼接xxx的贡献,即
gsx=gs+fsx g_{sx}=g_{s}+f_{sx} gsx=gs+fsx
每个xxx都可以贡献上gsg_{s}gs,于是
g[i][0]=∑x=0B−1(gs+devx)+∑x=0nums[i](gs+devx) g[i][0]=\sum_{x=0}^{B-1}(g_{s}+dev_{x})+\sum_{x=0}^{nums[i]}(g_{s}+dev_{x}) g[i][0]=x=0∑B−1(gs+devx)+x=0∑nums[i](gs+devx)
其中devxdev_{x}devx即添加一个特定xxx的贡献,我们已经计算有
f[i][0]=∑x=0B−1devx+∑x=0nums[i]−1devx f[i][0]=\sum_{x=0}^{B-1}dev_{x}+\sum_{x=0}^{nums[i]-1}dev_{x} f[i][0]=x=0∑B−1devx+x=0∑nums[i]−1devx
于是
g[i][0]=B×g[i+1][0]+nums[i]×g[i+1][1]+f[i][0] g[i][0]=B\times g[i+1][0]+nums[i]\times g[i+1][1]+f[i][0] g[i][0]=B×g[i+1][0]+nums[i]×g[i+1][1]+f[i][0]
同理可得
g[i][1]=∑x=nums[i]nums[i](g[i+1][1]+devx) g[i][1]=\sum_{x=nums[i]}^{nums[i]}(g[i+1][1]+dev_{x}) g[i][1]=x=nums[i]∑nums[i](g[i+1][1]+devx)
化简即
g[i][1]=g[i+1][1]×1+f[i][1] g[i][1]=g[i+1][1]\times 1+f[i][1] g[i][1]=g[i+1][1]×1+f[i][1]
于是分别计算[0,r][0,r][0,r]与[0,l−1][0,l-1][0,l−1]即可
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
using ll=long long;
const int N=100005;
const long long mod=20130427;
ll tot[N][2],totlen[N][2],g[N][2],f[N][2],B;
inline ll calc(int k){
return 1ll*k*(k-1)/2%mod;
}
inline void mmod(ll &k){
k=(k%mod+mod)%mod;
}
ll solve(ll *nums,int n)
{
memset(tot,0,sizeof(tot));
memset(totlen,0,sizeof(totlen));
memset(g,0,sizeof(g));
memset(f,0,sizeof(f));
tot[n][0]=nums[n]-1; tot[n][1]=1;
totlen[n][0]=nums[n]-1; totlen[n][1]=1;
f[n][0]=calc(nums[n]); f[n][1]=nums[n];
g[n][0]=f[n][0]; g[n][1]=f[n][1];
for(int i=n-1;i>=1;i--)
{
tot[i][0]=B*tot[i+1][0]%mod+nums[i]*tot[i+1][1]%mod+B-1;
tot[i][1]=tot[i+1][1];
totlen[i][0]=B*(totlen[i+1][0]+tot[i+1][0])%mod+nums[i]*(totlen[i+1][1]+tot[i+1][1])%mod+B-1;
totlen[i][1]=totlen[i+1][1]+tot[i+1][1];
f[i][0]=B*B*f[i+1][0]%mod+calc(B)*(totlen[i+1][0]+tot[i+1][0]+1)%mod+B*nums[i]*f[i+1][1]%mod+calc(nums[i])*(totlen[i+1][1]+tot[i+1][1])%mod;
f[i][1]=f[i+1][1]*B%mod+nums[i]*(totlen[i+1][1]+tot[i+1][1])%mod;
g[i][0]=g[i+1][0]*B%mod+g[i+1][1]*nums[i]%mod+f[i][0];
g[i][1]=g[i+1][1]*1%mod+f[i][1];
for(int j=0;j<=1;j++) mmod(tot[i][j]),mmod(totlen[i][j]),mmod(f[i][j]),mmod(g[i][j]);
}
return (g[1][0]+g[1][1])%mod;
}
ll nums[3][N];
int len[3];
int main()
{
cin>>B;
for(int i=1;i<=2;i++)
{
cin>>len[i];
for(int j=len[i];j>=1;j--) cin>>nums[i][j];
}
nums[1][1]--;
for(int i=1;i<=len[1];i++)
if(nums[1][i]<0) nums[1][i]+=B,nums[1][i+1]--;
if(nums[1][len[1]]==0) len[1]--;
printf("%lld\n",((solve(nums[2],len[2])-solve(nums[1],len[1]))%mod+mod)%mod);
return 0;
}
9275

被折叠的 条评论
为什么被折叠?



