HDU-4507-數位dp

題目大意 :給定區間,問滿足條件所有數的平方和;

題目解析:因爲要求平方和,所以要用結構體保存個數,和,平方和;

(附上大佬的解析)

需要維護三個值(推薦使用結構體), 假定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;
}


發佈了193 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章