HDU 4507(數位DP)
阿新 • • 發佈:2018-11-10
http://acm.hdu.edu.cn/showproblem.php?pid=4507
比如 個位為0,1,2,3,5,8,9,十位為1,那麼10,11,12,13,15,18,19都是符合要求的;
假設ans為2位的情況,temp為一位的情況。
結構體中cnt表示的是符合該種情況數的個數,sum表示符合該種情況數的和,ssum表示符合該種情況數的平方和。
在dfs至個位的情況時(i),temp.cnt=1,temp.sum=i,temp.ssum=i*i;
然後,返回第二位,ans.cnt+=temp.cnt;ans.sum+=temp.cnt*byte[2]+temp.sum(相當於10*7+0+1+2+3....)。
然後考慮這些數的平方和:考慮完全平方公式,所以對於10,11,12,13,15...19的平方和可以寫成(7*10+(0+1+2+3..9))的平方。注意取模。詳細見程式碼。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll Mod=1e9+7; struct node{ ll cnt,sum,ssum; node(){cnt=-1;sum=0;ssum=0;}; node(ll c,ll s,ll ss) { cnt=c;sum=s;ssum=ss; } }dp[20][10][10]; int a[20]; ll byte[20]; node dfs(int pos,int sum,int mod,bool limit) { if(pos==0) return sum&&mod?node(1,0,0):node(0,0,0); if(!limit&&dp[pos][sum][mod].cnt!=-1) return dp[pos][sum][mod]; int up=limit?a[pos]:9; node ans; ans.cnt=0; for(int i=0;i<=up;i++) { if(i==7) continue; node temp=dfs(pos-1,(sum+i)%7,(mod*10+i)%7,limit&&i==up); ans.cnt=(ans.cnt+temp.cnt)%Mod; ll t=i*byte[pos]%Mod*(temp.cnt%Mod)%Mod; ans.sum=(ans.sum+(t+temp.sum)%Mod)%Mod; ll tt=i*byte[pos]%Mod; ans.ssum=(ans.ssum+(temp.ssum+tt*tt%Mod*temp.cnt%Mod+2*tt%Mod*temp.sum%Mod)%Mod)%Mod; } if(!limit) dp[pos][sum][mod]=ans; return ans; } ll slove(ll n) { int tot=0; while(n) { a[++tot]=n%10; n/=10; } return dfs(tot,0,0,true).ssum; } void init() { byte[1]=1; for(int i=2;i<20;i++) byte[i]=byte[i-1]*10%Mod; } int main() { ios::sync_with_stdio(false); init(); int t; cin>>t; while(t--) { ll a,b; cin>>a>>b; cout<<(slove(b)-slove(a-1)+Mod)%Mod<<endl; } return 0; }