Problem
Description
Input
一行,两个整数l,r 。
Output
一行,一个整数,表示第l 天到第r 天的愉悦值的和。
Sample Input
Input 1
64 89
Input 2
3 233
Input 3
2333333333 66666666666666
Sample Output
Output 1
1818
Output 2
8730
Output 3
836269739
Data Constraint
Solution
其实我们并不用这么慌张。解题思想:分治
我们一位一位求答案,从左到右一位一位地固定。
假如要求1-4386的答案,那么我们可以分为:
1-999
1000-3999
4000-4299
4300-4379
4380-4385
4386
第一组最特殊,因为它跨了不止一个十进制位。
每一轮,我们进行以下操作:
如果它是最中间的那一位(此时总位数是单数),那么答案加上
(12+22+...+92)
*个数。
像下图,个数为每一位能放置的数的乘积。
如果不是最中间的那一位,那么答案加上45*45*方案数*2
(不要问我为什么*2,自己想。PS:45=1加到9,也等于0加到9)。
fo(i,1,a[0]-1)
{
gs*=s[i];
fo(j,1,i/2) sum=(sum+((gs/s[j]/s[i-j+1])%mo*2*45*45)%mo)%mo;
if (i%2) sum=(sum+((gs/s[i/2+1])%mo*285)%mo)%mo;
//算出总方案数,然后除以相应位置上的方案数,这样比一个一个位的方案数乘起来更快更方便
}
如果固定一位,那么固定的那位的方案数只能是1种。
其他步骤跟上述方法差不多,只需要研究一下固定后怎么搞就行了。
附:建议看多几个数组存一下认为重要的几个值,这样使思路更加清晰,改题改得更快。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define LL long long
#define mo 1000000007
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
LL I,L,R,gs,s1[20],s2[20],a[20],s[20],d[20],ans;
LL doit(LL x)
{
LL i,j,sum=0;
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
memset(s,0,sizeof(s));
while (x)
{
a[++a[0]]=x%10;
x/=10;
}
s[1]=9;fo(i,2,a[0]) s[i]=10;
fo(i,1,a[0]) d[i]=45;
gs=1;
fo(i,1,a[0]-1)
{
gs*=s[i];
fo(j,1,i/2) sum=(sum+((gs/s[j]/s[i-j+1])%mo*2*45*45)%mo)%mo;
if (i%2) sum=(sum+((gs/s[i/2+1])%mo*285)%mo)%mo;
}
s[a[0]]=9;s[1]=10;
fd(i,a[0],1)
{
if (!a[i] || i==a[0] && a[i]==1)
{
s[i]=1;
d[i]=a[i];
continue;
}
if (i==a[0]) s[i]=a[i]-1;
else s[i]=a[i];
gs=1;
fo(j,1,i) gs=gs*s[j];
d[i]=s1[a[i]-1];
fo(j,1,a[0]/2)
sum=(sum+((gs/s[j]/s[a[0]-j+1])%mo*2*d[j]*d[a[0]-j+1])%mo)%mo;
if (a[0]%2)
{
if ((a[0]/2+1)>i) sum=(sum+((gs/s[a[0]/2+1])%mo*a[a[0]/2+1]*a[a[0]/2+1])%mo)%mo;else
if ((a[0]/2+1)==i) sum=(sum+((gs/s[a[0]/2+1])%mo*s2[a[a[0]/2+1]-1])%mo)%mo;else
if ((a[0]/2+1)<i) sum=(sum+((gs/s[a[0]/2+1])%mo*s2[9])%mo)%mo;
}
s[i]=1;
d[i]=a[i];
}
fo(i,1,a[0]) sum=(sum+a[i]*a[a[0]-i+1])%mo;
return sum;
}
int main()
{
scanf("%lld%lld",&L,&R);
fo(I,1,9) s1[I]=s1[I-1]+I,s2[I]=s2[I-1]+I*I;
ans=((doit(R)-doit(L-1))%mo+mo)%mo;
printf("%lld",ans);
}