【题目】
Problem Description
单身!
依然单身!
吉哥依然单身!
DS 级码农吉哥依然单身!
所以,他生平最恨情人节,不管是
还是
,他都讨厌!
吉哥观察了 和 这两个数,发现:
最终,他发现原来这一切归根到底都是因为和 有关!所以,他现在甚至讨厌一切和 有关的数!
什么样的数和 有关呢?
如果一个整数符合下面 个条件之一,那么我们就说这个整数和 有关——
- 整数中某一位是 ;
- 整数的每一位加起来的和是 的整数倍;
- 这个整数是 的整数倍;
现在问题来了:吉哥想知道在一定区间内和 无关的数字的平方和。
Input
输入数据的第一行是 数 ( ),然后接下来的 行表示 个 ;每个 在一行内包含两个正整数 ( )。
Output
请计算 [ , ] 中和 无关的数字的平方和,并将结果对 求模后输出。
Sample Input
3
1 9
10 11
17 17
Sample Output
236
221
0
【分析】
终于把这道题弄出来了。。。
看到数据范围,很显然是一道数位 题
其实,如果只是统计与 无关的数的个数,就是常规操作,直接套板子就行了
但是现在是求平方和,该怎么办呢?
对每个节点都保存一个三元组, 为合法的数的个数, 为合法的数的和, 为合法的数的平方和
首先,我们先思考简单一点的,怎么求与 无关的数的和
假设现在 到了第 位,这一位填的数为 ,那么加上这一位 产生的贡献,和就是
记录的就是当前位置的和, 是不算上当前位置(就是之前的数的和)的和
现在就考虑如何算平方和( 表示不算上当前位,之前合法的数)
令 ,并拆开来化简得到
可以发现, 就是 , 就是 ,有关于 的暴力计算就行了
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Mod 1000000007
using namespace std;
int a[20],Pow[20];
struct dp{long long num,sum,squ;}f[20][10][10][2];
dp search(int p,int v1,int v2,bool limit)
{
int i,up;
dp ans=(dp){0,0,0};
if(!p) return (dp){v1&&v2,0,0};
if(~f[p][v1][v2][limit].num) return f[p][v1][v2][limit];
up=limit?a[p]:9;
for(i=0;i<=up;++i)
{
if(i==7) continue;
dp temp=search(p-1,(v1+i)%7,(v2*10+i)%7,limit&&a[p]==i);
ans.num=(ans.num+temp.num)%Mod;
ans.sum=(ans.sum+temp.sum+1ll*i*Pow[p-1]%Mod*temp.num%Mod)%Mod;
ans.squ=(ans.squ+temp.squ+2ll*i*Pow[p-1]%Mod*temp.sum%Mod+temp.num*i*i%Mod*Pow[p-1]%Mod*Pow[p-1]%Mod)%Mod;
}
f[p][v1][v2][limit]=ans;
return ans;
}
long long solve(long long x)
{
int p=0;
while(x!=0)
{
a[++p]=x%10;
x/=10;
}
memset(f,-1,sizeof(f));
return search(p,0,0,true).squ;
}
int main()
{
int n,i;
long long l,r;
scanf("%d",&n);
Pow[0]=1;
for(i=1;i<20;++i)
Pow[i]=10ll*Pow[i-1]%Mod;
for(i=1;i<=n;++i)
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",(solve(r)-solve(l-1)+Mod)%Mod);
}
return 0;
}