HDU-4507-数位dp

12 篇文章 0 订阅

题目大意 :给定区间,问满足条件所有数的平方和;

题目解析:因为要求平方和,所以要用结构体保存个数,和,平方和;

(附上大佬的解析)

需要维护三个值(推荐使用结构体), 假定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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值