您的位置:首页 > 其它

HDU 4507 吉哥系列故事——恨7不成妻 【数位DP】

2016-11-05 11:21 417 查看
题目:点击打开链接

题意:中文题

分析:由于题目要求的是区间内的满足条件的数的平方之和,所以不能用传统的只记录个数来做了。构造结构体记录数的个数,总和以及平方和。dp[pos][sta][smod][mod],sta表示数位是否存在7,smod表示当前的数对7取模的值,mod表示当前的数的每一个数位之和对7取模的值,易得出数的个数。然后可以通过数的个数,算出数的总和。

令pre=(先前数位的值)*(所在数位位置的十进制基数),tmp表示先前的各个满足条件的数,cnt表示先前数位的满足条件的数的个数,sum表示先前数位的数的个数,sq表示先前数位的数的平方之和。∑表示cnt个数值连加。

sum=∑tmp,

sq=∑tmp²,

cnt[new]=cnt[old]+cnt,

sum[new]=sum[old]+∑(tmp+pre)=sum[old]+∑tmp+cnt*pre=sum[old]+sum+cnt*pre,

sq[new]=sq[old]+∑(pre+tmp)²=sq[old]+∑(pre²+2*pre*tmp+tmp²)=sq[old]+cnt*pre²+2*pre*∑tmp+∑tmp²=sq[old]+cnt*pre²+2*pre*sum+sq,因此求出所有数平方之和了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define sqr(x) ((x)*(x))
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
const ll INF = 1e18;
const int inf=0x3f3f3f3f;
const int M=100010;
const int N=15;
const ll MOD=1000000007;
const double eps=1e-8;
const double pi=acos(-1.0);
using namespace std;
ll l,r,hsh[20];
int dig[20],vis[20][2][7][7];
struct node
{
ll cnt,sum,sq;
node(ll _cnt=0,ll _sum=0,ll _sq=0):cnt(_cnt),sum(_sum),sq(_sq){};
}dp[20][2][7][7];
void init()
{
hsh[0]=1;
for(int i=1;i<20;i++)
hsh[i]=hsh[i-1]*10%MOD;
}
node dfs(int pos,int sta,int smod,int mod,int lim)
{
if(pos==0) return node(sta==0&&smod&&mod,0,0);
if(!lim&&vis[pos][sta][smod][mod]) return dp[pos][sta][smod][mod];
int upper=lim?dig[pos]:9;
node nxt,res;
for(int i=0;i<=upper;i++)
{
nxt=dfs(pos-1,sta||(i==7),(smod*10+i)%7,(mod+i)%7,lim&&(i==upper));
ll pre=i*hsh[pos-1]%MOD;
res.cnt=(res.cnt+nxt.cnt)%MOD;
res.sum=(res.sum+nxt.sum+pre*nxt.cnt)%MOD;
res.sq=(res.sq+nxt.sq+pre*pre%MOD*nxt.cnt+2*pre*nxt.sum)%MOD;
}
if(!lim)
{
vis[pos][sta][smod][mod]=1;
dp[pos][sta][smod][mod]=res;
}
return res;
}
ll calc(ll x)
{
int len=0;
while(x)
{
dig[++len]=x%10;
x/=10;
}
return dfs(len,0,0,0,1).sq;
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d",&l,&r);
printf("%I64d\n",(calc(r)-calc(l-1)+MOD)%MOD);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: