NOIP提高组【JZOJ4799.】我的快乐时代

来源:互联网 发布:mac os x10.10 iso 编辑:程序博客网 时间:2024/05/01 03:49

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

这道题我们考虑一下类似数位dp的东西,答案=1~r的答案-1~l-1的答案,于是我们分开出答案,这里只举l-1的例子。我们枚举位数。

1、显然,在位数l-1的长度>k的时候,对于每两对di,dki+1,他们出现在1~l-1中的数量显然为910k3(因为第一位不能为0),特别的,当i=1时数量就为10k2。我们还要考虑一下当位数k为奇数的时候,那么显然中间的那个会出现(dk/2dk/2)的情况,这时的数量就为910k2。最后枚举一下这两个di,dki+1分别是什么,记录一下贡献即可。

2、在位数k=l-1的长度的时候,对于每两对di,dki+1,这时要考虑的情况就比较多了。我们枚举前x位与l-1的前x位相等,那么剩下的数量显然就是lx+110lenlx1+1,最后枚举一下这两个di,dki+1分别是什么,记录一下贡献即可。

代码

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const ll maxn=1000000007;ll l,r,i,t,j,k,len1,len2,x,y,f[20],ans1,ans2,a[20],b[20],c[20],d[20],l1,r1;int dg(ll len1){    ll i,j,t,k,l,x,y,ans1=0;    for (i=1;i<len1;i++){        t=i/2;        for (j=2;j<=t;j++)            for (k=1;k<=9;k++)                for (l=1;l<=9;l++) ans1=(ans1+f[i-3]*k*l*18%maxn)%maxn;        if (i!=1){            for (k=1;k<=9;k++)                for (l=1;l<=9;l++)ans1=(ans1+f[i-2]*k*l*2%maxn)%maxn;        }        if (!(i%2))continue;        if (i!=1){            for (k=1;k<=9;k++)                ans1=(ans1+f[i-2]*9*k*k%maxn)%maxn;        }else ans1=285;    }    t=len1/2;    for (j=1;j<=t;j++)        for (k=1;k<=9;k++)            for (l=1;l<=9;l++){                if (j==1 && l>a[len1-j+1]) break;                ans1=(ans1+c[len1-j+1]*k*l%maxn*f[len1-j-1]%maxn*2%maxn)%maxn;                if (l>a[len1-j+1]) continue;                if (l<a[len1-j+1]) ans1=(ans1+k*l*f[len1-j-1]*2%maxn)%maxn;                if (l==a[len1-j+1]){                    for (x=len1-j;x>j;x--)                        ans1=(ans1+k*l*f[x-2]*a[x]*2%maxn)%maxn;                    if (k<a[j]) ans1=(ans1+k*l*f[j-1]*2%maxn)%maxn;                    if (k==a[j]){                        for (x=j-1;x>0;x--)                            ans1=(ans1+k*l*f[x-1]*a[x]*2%maxn)%maxn;                        ans1=(ans1+k*l*2)%maxn;                    }                }            }    if (len1%2){        if (len1==1){            for (i=1;i<=a[1];i++)                ans1+=i*i;            return ans1;        }        t++;        for (k=1;k<=9;k++){            l=k;            ans1=(ans1+c[t]*k%maxn*k%maxn*f[t-1]%maxn)%maxn;            if (l>a[t]) continue;            if (l<a[t]) ans1=(ans1+k*k*f[t-1]%maxn)%maxn;            if (l==a[t]){                for (x=t-1;x>0;x--)                    ans1=(ans1+k*k*f[x-1]*a[x]%maxn)%maxn;                ans1=(ans1+k*k%maxn)%maxn;            }        }    }    return ans1;}int main(){//  freopen("data.in","r",stdin);    scanf("%lld%lld",&l1,&r1);l1--;    t=l1;    f[0]=1;    for (i=1;i<=18;i++)        f[i]=f[i-1]*10;    while (t)a[++len1]=t%10,t=t/10;    for (i=1;i<len1;i++)        c[i]=(l1/f[i]-f[len1-i-1])%maxn;    t=r1;    while (t)b[++len2]=t%10,t=t/10;    for (i=1;i<len2;i++){        t=r1/f[i];        d[i]=(t-f[len2-i-1])%maxn;    }    for (i=1;i<=18;i++)        f[i]=f[i]%maxn;    ans1=dg(len1);    for (i=0;i<=len2;i++)        c[i]=d[i],a[i]=b[i];    ans2=dg(len2);    ans2=(ans2+maxn-ans1)%maxn;    printf("%d\n",ans2);}
3 0