1. 程式人生 > >【HDU 4507】吉哥系列故事——恨7不成妻

【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(