【HDU 4507】吉哥系列故事——恨7不成妻

【题目】

传送门

Problem Description

单身!
依然单身!
吉哥依然单身!
DS 级码农吉哥依然单身!
所以,他生平最恨情人节,不管是 214 214 还是 77 77 ,他都讨厌!

吉哥观察了 214 214 77 77 这两个数,发现:

2 + 1 + 4 = 7 2+1+4=7
7 + 7 = 7 2 7+7=7*2
77 = 7 11 77=7*11

最终,他发现原来这一切归根到底都是因为和 7 7 有关!所以,他现在甚至讨厌一切和 7 7 有关的数!

什么样的数和 7 7 有关呢?

如果一个整数符合下面 3 3 个条件之一,那么我们就说这个整数和 7 7 有关——

  1. 整数中某一位是 7 7
  2. 整数的每一位加起来的和是 7 7 的整数倍;
  3. 这个整数是 7 7 的整数倍;

现在问题来了:吉哥想知道在一定区间内和 7 7 无关的数字的平方和。

Input

输入数据的第一行是 c a s e case t t 1 t 50 1 \le t ≤ 50 ),然后接下来的 t t 行表示 t t c a s e case ;每个 c a s e case 在一行内包含两个正整数 l , r l, r 1 l r 1 0 18 1 \le l \le r \le 10^{18} )。

Output

请计算 [ l l , r r ] 中和 7 7 无关的数字的平方和,并将结果对 1 0 9 + 7 10^9 + 7 求模后输出。

Sample Input

3
1 9
10 11
17 17

Sample Output

236
221
0


【分析】

终于把这道题弄出来了。。。

看到数据范围,很显然是一道数位 d p dp

其实,如果只是统计与 7 7 无关的数的个数,就是常规操作,直接套板子就行了

但是现在是求平方和,该怎么办呢?

对每个节点都保存一个三元组, n u m num 为合法的数的个数, s u m sum 为合法的数的和, s q u squ 为合法的数的平方和

首先,我们先思考简单一点的,怎么求与 7 7 无关的数的

假设现在 d p dp 到了第 p o s pos 位,这一位填的数为 i i ,那么加上这一位 i i 产生的贡献,和就是

n o w . s u m + = t e m p . s u m + t e m p . n u m i 1 0 p o s 1 now.sum+=temp.sum+temp.num*i*10^{pos-1}

n o w . s u m now.sum 记录的就是当前位置的和, t e m p . s u m temp.sum 是不算上当前位置(就是之前的数的和)的和

现在就考虑如何算平方和 a a 表示不算上当前位,之前合法的数)

n o w . s q u = ( a + i 1 0 p o s 1 ) 2 now.squ=\sum(a+i*10^{pos-1})^2

b = i 1 0 p o s 1 b=i*10^{pos-1} ,并拆开来化简得到

n o w . s q u = ( a 2 + 2 a b + b 2 ) = a 2 + 2 b a + b 2 now.squ=\sum (a^2+2ab+b^2)=\sum a^2+2b\sum a+\sum b^2

可以发现, a 2 \sum a^2 就是 t e m p . s q u temp.squ a \sum a 就是 t e m p . s u m temp.sum ,有关于 b b 的暴力计算就行了


【代码】

#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;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/83780000