題目大意 :給定區間,問滿足條件所有數的平方和;
題目解析:因爲要求平方和,所以要用結構體保存個數,和,平方和;
(附上大佬的解析)
需要維護三個值(推薦使用結構體), 假定dfs推出返回的結構體是next,當前結果的結構體是ans
①符合條件數的個數 cnt
②符合條件數的和 sum
③符合添加數的平方和 sqsum
其中①是基礎數位DP。②next.sum+(10^len*i)*ans.cnt,其中(10^len*i)*ans.cnt代表以len爲首位的這部分數字和。
③首先重建一下這個數,(10^len*i+x),其中x是這個數的後面部分,則平方和就是(10^len*i)^2+x^2+2*10^len*i*x,其中x^2=next.sqsum
整體還要乘以next.cnt,畢竟不止一個。
這樣sqsum+=next.sqsum
sqsum+=(2*10^len*i*x)*next.cnt=(2*10^len*i)*next.sum(神奇的化簡)
sqsum+=(10^len*i)^2*next.cnt
AC代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1000000007;
struct node
{
ll cnt,sum,sq;
node(){cnt=-1,sum=0,sq=0;}
node(ll cnt,ll sum,ll sq):cnt(cnt),sum(sum),sq(sq){}
}dp[20][10][10];
ll num[20],p[20];
node dfs(int pos,int mod1,int mod2,bool limit)
{
if(pos==-1)
{
if(mod1!=0&&mod2!=0)
return node(1,0,0);
else
return node(0,0,0);
}
if(!limit&&dp[pos][mod1][mod2].cnt!=-1) return dp[pos][mod1][mod2];
int u=limit?num[pos]:9;
node ans;
ans.cnt=0;
for(int i=0;i<=u;i++)
{
if(i==7) continue;
node t=dfs(pos-1,(mod1+i)%7,(mod2*10+i)%7,limit&&i==u);
ans.cnt+=t.cnt;
ans.cnt%=mod;
ans.sum+=(t.sum+((p[pos]*i)%mod*t.cnt)%mod)%mod;
ans.sum%=mod;
ans.sq+=(t.sq+((2*p[pos]*i)%mod)*t.sum)%mod;
ans.sq%=mod;
ans.sq+=(i*i)%mod*p[pos]%mod*p[pos]%mod*t.cnt%mod;
ans.sq%=mod;
}
if(!limit) return dp[pos][mod1][mod2]=ans;
return ans;
}
ll solve(ll n)
{
int cnt=0;
while(n)
{
num[cnt++]=n%10;
n/=10;
}
return dfs(cnt-1,0,0,true).sq;
}
int main()
{
int cas;
p[0]=1;
for(int i=1;i<20;i++) p[i]=p[i-1]*10%mod;
scanf("%d",&cas);
while(cas--)
{
ll a,b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",(solve(b)-solve(a-1)%mod+mod)%mod);
}
return 0;
}