您的位置:首页 > 其它

hdu 4507 数位dp(好题)

2017-11-28 18:32 232 查看
题解:数位dp

和简单的数位dp不同,这道题要算所有合法数的平方和

考虑到一个数可以写成X=ΣAi*Pi,(其中Ai为X每一位的值,Pi=10^i)

因为(A+B)^2=A*A+2*A*B+B*B

(X1+X2+X3+...+Xn)^2=X1^2+2*X1*(X2+X3+...+Xn)+(X2+X3+...+Xn)^2

=X1^2+2*X1*(X2+X3+...+Xn)+X2^2+2*X2*(X3+...+Xn)+(X3+...+Xn)^2

...

一直递归分治,即可求的

因此在dp时,只要记录当前状态合法数的数量cnt,当前状态之后的和sum,平方和sqr

A=Ai*Pi

now.cnt=now.cnt+nxt.cnt;

now.sum=now.sum+nxt.sum+A*nxt.cnt;

now.sqr=now.sqr+A*A*nxt.cnt+2*A*nxt.sum+nxt.sqrt;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define clr(x,y) memset(x,y,sizeof x)
const ll Mod = 1e9 + 7;
const int maxn = 100 + 10;

int bits[maxn];
struct Node
{
ll cnt,sum,sums;
}dp[20][7][7];
bool vis[20][7][7];
ll a[maxn];
Node dfs(int pos,ll sum,int remain,int remains,bool flag)
{
if(pos < 0)
{
if(remain % 7 && remains % 7)return (Node){1,0,0};
else return (Node){0,0,0};
}
if(!flag && vis[pos][remain][remains])
return dp[pos][remain][remains];
int up = flag ? bits[pos] : 9;
Node ret = (Node){0,0,0};
for(int i = 0; i <= up;i ++)
{
if(i == 7)continue;
Node temp = dfs(pos - 1,(sum * 10 + i) % Mod,(remain + i) % 7,(remains * 10 + i) % 7,flag && i == up);
ll A = a[pos] * i % Mod;
ret.cnt = (ret.cnt + temp.cnt) % Mod;
ret.sum = (ret.sum + A * temp.cnt % Mod + temp.sum ) % Mod;
ret.sums = (ret.sums + A * A % Mod * temp.cnt % Mod + 2 * A * temp.sum % Mod+ temp.sums) % Mod;
}
if(!flag)
{
vis[pos][remain][remains] = true;
dp[pos][remain][remains] = ret;
}
return ret;
}
ll calc(ll n)
{
int len = 0;
while(n)
{
bits[len ++] = n % 10;
n /= 10;
}
return dfs(len - 1,0,0,0,true).sums;
}
int main()
{
clr(vis,false);
a[0] = 1;
for(int i = 1;i <= 18;i ++)
a[i] = a[i - 1] * 10;
int Tcase;scanf("%d",&Tcase);
while( Tcase --)
{
ll n,m;scanf("%lld%lld",&n,&m);
ll ans = calc(m) - calc(n - 1);
ans = (ans + Mod) % Mod;
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: