【JZOJ4799】我的快乐时代

来源:互联网 发布:java date 加减 编辑:程序博客网 时间:2024/05/04 14:03

Description

这里写图片描述
原题为51Nod卷积和

Solution

设第一天到第i天的答案为solve(i),那么第l天到第r天答案可以分解为:solve(r)solve(l1)

然后我们现在要解决Solve(n)

n是个m位数。

假设m=5,我们可以先快速求出1~9,10~99,100~999,1000~9999的卷积和。

那么怎么计算呢?

我们知道,1~9就是12+22+…+92=285。

10~99自己算。

对于长度为L(L>2)的,我们假设在开头结尾算,那么卷积和为:
10L29i=1i9i=0i+9(9i=0i)210L3(想想看为什么)

那么对于长度为m的,例如有一个数abcde¯¯¯¯¯¯¯¯

我们就分开处理,先处理10000(a1)9999¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯,再处理a0000¯¯¯¯¯¯¯¯¯a(c1)999¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯……

至于计算的方法,其实和前面的差不多,只是要固定一些数字。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define ll long long#define mo 1000000007#define N 20using namespace std;ll qz[30]={0,1,3,6,10,15,21,28,36,45,0,1,2,3,4,5,6,7,8,9};ll pf[30]={0,1,5,14,30,55,91,140,204,285,0,1,4,9,16,25,36,49,64,81};ll z[N];int q[N];void get(ll x){    q[0]=0;    if(!x) q[0]=1,q[1]=0;    while(x) q[++q[0]]=x%10,x/=10;}int fw[N],ct[N];ll calc(ll n){    if(n<1) return 0;    ll ans=0;    get(n);    fo(i,1,q[0]-1)    {        if(i==1)        {            ans=(ans+285)%mo;            continue;        }        else if(i==2)        {            ans=(ans+4050)%mo;            continue;        }        ans=(ans+4050*z[i-2]%mo+4050*9%mo*z[i-3]%mo*(i/2-1)%mo)%mo;        if(i%2==1) ans=(ans+285*9%mo*z[i-2]%mo)%mo;    }    fd(i,q[0],1)    {        ct[i]=10;        fw[i]=9;    }    if(q[0]==1) ans=(ans+pf[q[1]]%mo)%mo;    else if(q[0]==2) ans=(ans+qz[q[2]-1]*45*2%mo+q[2]*qz[q[1]]*2%mo)%mo;    else    fd(i,q[0],1)    {        ct[i]=q[i]-1;        if(i!=q[0]) ct[i]++;        fw[i]=q[i]-1;        if(i==1) fw[i]++,ct[i]++;        int p=q[0]/2;        fo(j,1,p)        {            int k=q[0]-j+1;            ll tmp=0;            if(j==1) tmp=(tmp+qz[fw[j]]*qz[fw[k]]%mo*2%mo)%mo;            else tmp=(tmp+qz[fw[j]]*qz[fw[k]]%mo*2%mo)%mo;            fo(l,1,q[0])            if(l!=j && l!=k) tmp=tmp*ct[l]%mo;            ans=(ans+tmp)%mo;        }        if(q[0]%2==1)        {            p++;            ll tmp=0;            tmp=pf[fw[p]];            fo(j,1,q[0])            if(j!=p) tmp=tmp*ct[j]%mo;            ans=(ans+tmp)%mo;        }        fw[i]=q[i]+10;        ct[i]=1;    }    return ans;}int main(){     z[0]=1;    fo(i,1,N-1) z[i]=z[i-1]*10%mo;    ll l,r;    cin>>l>>r;    cout<<(calc(r)-calc(l-1)+mo)%mo;}
1 0
原创粉丝点击