Description
Solution
这道题虽然相对套路,但还是蛮考人的
我们要求的实际上就是∑d⌊n111...1⌋(d个1)\sum\limits_{d} {\lfloor{n\over 111...1}\rfloor}(d个1)d∑⌊111...1n⌋(d个1)
有一个套路就是上下同时乘9
令N=9nN=9nN=9n
那就变成了∑d≥2⌊N10d−1⌋\sum\limits_{d\geq 2}{{\lfloor{N\over 10^d-1}\rfloor}}d≥2∑⌊10d−1N⌋
考虑将NNN写成10dx+y10^dx+y10dx+y的形式,那么⌊N10d−1⌋=x+⌊x+y10d−1⌋{\lfloor{N\over 10^d-1}\rfloor}=x+{\lfloor{x+y\over 10^d-1}\rfloor}⌊10d−1N⌋=x+⌊10d−1x+y⌋
相当于对于我们将N分割成若干长度为d的段,每一段会给后面的所有段都贡献
先不考虑后面的余数
对于第i个位置,它会对i-d,i-2d,i-3d,i-4d都贡献
我们如果枚举d暴力算的话复杂度显然不能接受
仔细观察,实际上它可以写成卷积的形式,即-kd与i的卷积,于是可以用FFT或NTT解决(结果不是很大)
那么前面的部分就算完了,考虑最后剩下来的余数
我们枚举d,暴力求解的话我们需要对于每一段都加在一起再高精度除法,这显然也不能接受
然而我们发现除出来答案不会很大,并且由于数据随机,有很大概率只有最高那几位是有用的。
那我们可以暴力取每一段的前15位,然后直接用10^15-1去除即可。
注意10^15并没有超过long long,而一个高精度数除以long long是容易做的。
这样我们就在llogll\log lllogl的时间复杂度做完了。
Code
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 500205
#define M 524288
#define L 19
#define LL long long
#define LT unsigned long long
#define mo1 4294967296
#define mo 998244353
using namespace std;
int n,a[N],bit[M+1];
LT sv;
LL u1[M+1],u2[M+1],wi[M+1],ny,c[101];
LL ksm(LL k,LL n)
{
LL s=1;
for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
return s;
}
void prp()
{
wi[0]=1,wi[1]=ksm(3,(mo-1)/M);
fo(i,1,M)
{
bit[i]=(bit[i>>1]>>1)|((i&1)<<(L-1));
wi[i]=wi[i-1]*wi[1]%mo;
}
ny=ksm(M,mo-2);
}
void NTT(LL *a,bool pd)
{
fo(i,0,M-1) if(i<bit[i]) swap(a[i],a[bit[i]]);
LL v;
for(int h=1,m=2,lim=M>>1;m<=M;lim>>=1,h=m,m<<=1)
{
for(int j=0;j<M;j+=m)
{
fo(i,0,h-1)
{
v=((!pd)?wi[i*lim]:wi[M-i*lim])*a[i+j+h]%mo;
a[i+j+h]=(a[i+j]-v+mo)%mo;
a[i+j]=(a[i+j]+v)%mo;
}
}
}
if(pd) fo(i,0,M-1) a[i]=a[i]*ny%mo;
}
int main()
{
cin>>n>>sv;
sv%=mo1;
LT ua=747796405,ub=1403630843;
fo(i,1,n)
{
a[n-i]=(sv/1024)%10;
sv=(sv*ua%mo1-ub+mo1)%mo1;
}
fod(j,n-1,0)
{
a[j]*=9;
a[j+1]+=a[j]/10;
a[j]%=10;
}
fo(j,0,n-1) a[j+1]+=a[j]/10,a[j]%=10;
while(a[n]>0) n++;
while(n>1&&a[n-1]==0) n--;
prp();
fo(i,2,n) for(int j=1;i*j<=n;j++) u2[n-i*j]++;
fo(i,0,n-1) u1[i]=a[i];
NTT(u1,0),NTT(u2,0);
fo(i,0,M-1) u1[i]=u1[i]*u2[i]%mo;
NTT(u1,1);
fo(i,0,n-1) u1[i]=u1[i+n];
fo(i,n,M-1) u1[i]=0;
fo(j,0,n-1) u1[j+1]+=u1[j]/10,u1[j]%=10;
while(u1[n]>0)
{
while(u1[n]) n++;
fo(j,0,n-1) u1[j+1]+=u1[j]/10,u1[j]%=10;
}
while(n&&!u1[n-1]) n--;
fo(i,2,n)
{
int w=min(i,15),e=w;
memset(c,0,sizeof(c));
for(int j=0;j*i<=n+1;j++)
{
int l=(j+1)*i-w;
fo(p,0,w-1) c[p]+=a[l+p];
}
fo(j,0,e-1) c[j+1]+=c[j]/10,c[j]%=10;
while(c[e]>0)
{
while(c[e]>0) e++;
fo(j,0,e-1) c[j+1]+=c[j]/10,c[j]%=10;
}
LL vl=9,sm=0,al=0;
fo(j,1,w-1) vl=vl*(LL)10+9;
fod(j,e-1,0)
al=(al*(LL)10+c[j]),sm=(sm*(LL)10+al/vl),al%=vl;
for(int c1=0;sm;c1++,sm/=10) u1[c1]+=sm%10;
}
fo(j,0,n-1) u1[j+1]+=u1[j]/10,u1[j]%=10;
while(u1[n]) n++;
if(n==0) printf("0\n");
else
{
fod(i,n-1,0) printf("%d",u1[i]);
}
}