測試地址:Seven
作法: 本題須要用到數位DP。
是的,我看這題題目名字實在太長,就本身給取了個名字…首先看它給的條件,若是隻求數字個數的話,很是明顯是數位DP的形式,只須要設
爲前
位中,不卡上界的,數位和對
的餘數爲
,數對
的餘數爲
的數字的個數,很容易就能轉移。而要求數字的和較難一點,但咱們也能較快地想出轉移。而如今要求數字的平方和,這就有點複雜了。
然而實際上也不很複雜,你只須要一個結論:一些數的平方和,等於這些數和的平方,減去這些數兩兩間的乘積之和乘
。這個結論也很容易理解,由於
,移項便可獲得上面的結論。這樣一來,咱們須要求
,表示知足對應條件(和上面狀態定義同樣,就不重複寫了)的數的和,還有
,表示知足對應條件的數兩兩之間乘積的和。
咱們發現全部轉移均可以轉化爲如下問題:咱們有兩個集合,分別求出了對應的
和
,它們合併以後的
和
怎麼求?這個比較好推,就本身推一下就好了,實在不懂就看我代碼。還有一個問題是,咱們有一個集合,求出了對應的
和
,那麼在這些集合的數以後添加一位數
後,集合的
和
怎麼變化?這個就稍微複雜一些,以三個數的集合
爲例,令新加的位爲
,則:
根據這兩個式子咱們能夠找到規律,首先
不變,
就等於原來的
乘
加上
乘
,而
等於原來的
乘
,加上
原來的
,最後加上
。
有了這些東西,就能夠解決轉移的問題了,像模板數位DP同樣作就好了。
如下是本人代碼:php
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1000000007; const ll inv2=500000004; int T,n; ll s[25],num[25][7][7],f[25][7][7],g[25][7][7]; void update(int dgt,int j,int k,ll nowf,ll nowg,ll nownum) { g[dgt][j][k]=(g[dgt][j][k]+nowg+nowf*f[dgt][j][k])%mod; f[dgt][j][k]=(f[dgt][j][k]+nowf)%mod; num[dgt][j][k]=(num[dgt][j][k]+nownum)%mod; } ll solve() { int nowi=0,nowj=0,nowk=0; ll nowsum=0; memset(f[n+1],0,sizeof(f[n+1])); memset(g[n+1],0,sizeof(g[n+1])); memset(num[n+1],0,sizeof(num[n+1])); for(int dgt=n;dgt>=1;dgt--) { memset(f[dgt],0,sizeof(f[dgt])); memset(g[dgt],0,sizeof(g[dgt])); memset(num[dgt],0,sizeof(num[dgt])); for(int j=0;j<7;j++) for(int k=0;k<7;k++) for(int now=0;now<=9;now++) { if (now==7) continue; int newj=(j+now)%7,newk=(k*10ll+now)%7; ll nowf=(f[dgt+1][j][k]*10ll%mod+now*num[dgt+1][j][k]%mod)%mod; ll nowg=g[dgt+1][j][k]*100ll%mod; nowg=(nowg+f[dgt+1][j][k]*now%mod*10ll%mod*(num[dgt+1][j][k]-1ll+mod)%mod)%mod; nowg=(nowg+num[dgt+1][j][k]*(num[dgt+1][j][k]-1ll)%mod*inv2%mod*now*now%mod)%mod; ll nownum=num[dgt+1][j][k]; update(dgt,newj,newk,nowf,nowg,nownum); } if (dgt<n&&(!nowi)) { for(int now=0;now<s[dgt];now++) { if (now==7) continue; int newj=(nowj+now)%7,newk=(nowk*10ll+now)%7; update(dgt,newj,newk,(nowsum*10ll+now)%mod,0ll,1ll); } } nowi=(nowi||(s[dgt]==7)); nowj=(nowj+s[dgt])%7; nowk=(nowk*10ll+s[dgt])%7; nowsum=(nowsum*10ll+s[dgt])%mod; for(int now=1;now<=((dgt==n)?(s[dgt]-1):9);now++) { if (now==7) continue; update(dgt,now%7,now%7,now,0ll,1ll); } } f[0][0][0]=g[0][0][0]=num[0][0][0]=0; for(int j=1;j<7;j++) for(int k=1;k<7;k++) update(0,0,0,f[1][j][k],g[1][j][k],num[1][j][k]); ll ans=((f[0][0][0]*f[0][0][0]%mod-g[0][0][0]*2ll)%mod+mod)%mod; if ((!nowi)&&nowj&&nowk) ans=(ans+nowsum*nowsum)%mod; return ans; } int main() { scanf("%d",&T); while(T--) { ll ans=0,x; scanf("%lld",&x); x--; if (x) { n=0; while(x) { s[++n]=x%10; x/=10; } ans=(mod-solve())%mod; } scanf("%lld",&x); n=0; while(x) { s[++n]=x%10; x/=10; } ans=(ans+solve())%mod; printf("%lld\n",ans); } return 0; }