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


    题目

    这里写图片描述

    分析

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

    当len>i

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

    当len=i

    这部分有点麻烦,因为这个i位数不能大于x
    同样枚举一个位置j,k为他的相对位置,再枚举j和k这两个位置分别取什么数,设分别取p和q。
    所以,我们打一个数位dp,从首位开始做
    (f_{l,0或1})表示,做完了前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);
    }
    
    
  • 相关阅读:
    day15内置函数
    day14生成器进阶
    day13迭代器、生成器
    day12装饰器进阶
    day11装饰器
    day10函数进阶
    day9函数
    day8文件操作
    正则表达式
    初识递归
  • 原文地址:https://www.cnblogs.com/chen1352/p/9051692.html
Copyright © 2020-2023  润新知