【NOIP2016提高A组模拟9.24】我的快乐时代

题目

这里写图片描述

分析

虽然我们很难求出 mi=njoy(i)
但是我们可以分别求出 mi=1joy(i) n1i=1joy(i) ,相减就可以了。
如果我们要求 xi=1joy(i)
设x的长度为len,
接着枚举i,求出所有i位数的贡献。
分两种情况:

当len>i

接着我们枚举一个位置j,
k为他的相对位置,
再枚举j和k这两个位置分别取什么数,设分别取p和q。
因为这个i位数一定小于x,所以剩下的位置可以随便取(注意j、k重合的情况,以及首位只能取1~9)
这里写图片描述
每个这样的j、k、p和q,贡献就是 pq

当len=i

这部分有点麻烦,因为这个i位数不能大于x
同样枚举一个位置j,k为他的相对位置,再枚举j和k这两个位置分别取什么数,设分别取p和q。
所以,我们打一个数位dp,从首位开始做
fl,01 表示,做完了前l位,这前l位是否与x的前l位相等,是为1,否则为0。
转移很简单,对于l=j、l=k的情况特殊判断。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=1000000007;
const long long N=50005;
using namespace std;
long long n,m,ans,a[N],mi[19],f[20][2];
long long mi1(long long x,long long y)
{
    long long sum=1;
    while(y)
    {
        if(y&1) sum=sum*x%mo;
        x=x*x%mo;
        y/=2;
    }
    return sum;
}
long long cale(long long x)
{
    long long sum=0;
    for(long long i=1;x>mi[i] && i<=18;i++)
    {
        if(x/mi[i+1])
        {
            for(long long j=1;j<=i;j++)
            {
                long long k=(i-j+1);
                if(j==k)
                {
                    if(i==1)
                    {
                        sum=(sum+285)%mo;
                    }
                    else
                    {
                        sum=(sum+285*9*mi1(10,i-2)%mo)%mo;
                    }
                }
                else
                if(j==1 || k==1)
                {
                    sum=(sum+45*45*mi1(10,i-2)%mo)%mo;
                }
                else
                {
                    sum=(sum+45*45*9*mi1(10,i-3)%mo)%mo;
                }
            }
        }
        else
        {
        for(long long j=1;j<=i;j++)
        {
            long long k=(i-j+1);
            if(j!=k)
            for(long long p=1;p<=9;p++)
                for(long long q=1;q<=9;q++)
                {
                    long long num=p*mi[j]+q*mi[k],value=0;
                    if(num<=x)
                    {
                        memset(f,0,sizeof(f));
                        if(j==i)
                        {
                            if(p==x/mi[i]) f[i][1]=1;
                            else f[i][0]=1;
                        }
                        else
                        if(k==i)
                        {
                            if(q==x/mi[i]) f[i][1]=1;
                            else f[i][0]=1;
                        }
                        else
                        {
                            for(int l=1;l*mi[i]<=x;l++) f[i][0]++;
                            f[i][0]--;
                            f[i][1]++;
                        }
                        for(int l=i-1;l>=1;l--)
                        {
                            if(l==j)
                            {
                                if(p>(x%mi[l+1])/mi[l])
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                else
                                if(p==(x%mi[l+1])/mi[l])
                                {
                                    f[l][1]=(f[l][1]+f[l+1][1])%mo;
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                }
                                else
                                {
                                    f[l][0]=(f[l][0]+f[l+1][0]+f[l+1][1])%mo;
                                }
                            }
                            else
                            if(l==k)
                            {
                                if(q>(x%mi[l+1])/mi[l])
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                else
                                if(q==(x%mi[l+1])/mi[l])
                                {
                                    f[l][1]=(f[l][1]+f[l+1][1])%mo;
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                }
                                else
                                {
                                    f[l][0]=(f[l][0]+f[l+1][0]+f[l+1][1])%mo;
                                }
                            }
                            else
                            for(int l1=0;l1<=9;l1++)
                            {
                                if(l1>(x%mi[l+1])/mi[l])
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                else
                                if(l1==(x%mi[l+1])/mi[l])
                                {
                                    f[l][1]=(f[l][1]+f[l+1][1])%mo;
                                    f[l][0]=(f[l][0]+f[l+1][0])%mo;
                                }
                                else
                                {
                                    f[l][0]=(f[l][0]+f[l+1][0]+f[l+1][1])%mo;
                                }
                            }
                        }
                        value=(f[1][0]+f[1][1])%mo;
                        sum=(sum+q*p%mo*value%mo)%mo;
                    }
                }
        }
        long long j=i/2+1;
        if(i%2)
            for(int p=1;p<=9;p++)
            if(p*mi[j]<=x)
            {
                memset(f,0,sizeof(f));
                    if(j==i)
                    {
                        if(p==(x%mi[i+1])/mi[i]) f[i][1]=1;
                            else f[i][0]=1;
                    }
                    else
                    {
                        for(int l=1;l*mi[i]<=x;l++)
                        {
                            f[i][0]++;
                        }
                        f[i][0]--;
                        f[i][1]++;
                    }
                    for(int l=i-1;l>=1;l--)
                    {
                        if(l==j)
                        {
                            if(p>(x%mi[l+1])/mi[l])
                                f[l][0]=(f[l][0]+f[l+1][0])%mo;
                            else
                            if(p==(x%mi[l+1])/mi[l])
                            {
                                f[l][1]=(f[l][1]+f[l+1][1])%mo;
                                f[l][0]=(f[l][0]+f[l+1][0])%mo;
                            }
                            else
                            {
                                f[l][0]=(f[l][0]+f[l+1][0]+f[l+1][1])%mo;
                            }
                        }
                        else
                        for(int l1=0;l1<=9;l1++)
                        {
                            if(l1>(x%mi[l+1])/mi[l])
                                f[l][0]=(f[l][0]+f[l+1][0])%mo;
                            else
                            if(l1==(x%mi[l+1])/mi[l])
                            {
                                f[l][1]=(f[l][1]+f[l+1][1])%mo;
                                f[l][0]=(f[l][0]+f[l+1][0])%mo;
                            }
                            else
                            {
                                f[l][0]=(f[l][0]+f[l+1][0]+f[l+1][1])%mo;
                            }
                        }
                    }
                    sum=(sum+p*p%mo*(f[1][0]+f[1][1])%mo)%mo;
            }
        }
    }
    return sum;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    mi[1]=1;
    for(long long i=2;i<=19;i++)
    {
        mi[i]=mi[i-1]*10;
    }
        printf("%lld",(cale(m)-cale(n-1)+mo)%mo);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值