【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);
}

原文地址:https://www.cnblogs.com/chen1352/p/9051692.html