hdu 4507 恨7不成妻(数位dp)
Posted jpphy0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4507 恨7不成妻(数位dp)相关的知识,希望对你有一定的参考价值。
问题
hdu 4507 恨7不成妻 - https://acm.hdu.edu.cn/showproblem.php?pid=4507
分析
参照
- 详细讨论参照Bomb
状态设计
- s t a t e 1 ∈ { 0 、 1 、 2 、 3 、 4 、 5 、 6 } state1\\in \\{0、1、2、3、4、5、6\\} state1∈{0、1、2、3、4、5、6}
- s t a t e 2 ∈ { 0 、 1 、 2 、 3 、 4 、 5 、 6 } state2\\in \\{0、1、2、3、4、5、6\\} state2∈{0、1、2、3、4、5、6}
-
d
p
[
m
]
[
s
t
a
t
e
1
]
[
s
t
a
t
e
2
]
dp[m][state1][state2]
dp[m][state1][state2]:长度为m位的数,且同时满足以下三个条件时的数的个数
- 各个位上的数字的和模 7 7 7 的余数不等于 s t a t e 1 state1 state1
- 数模 7 7 7 的余数不等于 s t a t e 2 state2 state2
- 数不含 7 7 7
计算
- 例如:求4578以内的与7无关的数的平方和
- 当最高位取3时, ∑ 1 k ( 3 x y z ) 2 = ∑ 1 k ( 3 × 1 0 3 + x y z ) 2 = ∑ 1 k ( 3 × 1 0 3 ) 2 + 2 × ( 3 × 1 0 3 ) × ∑ 1 k x y z + ∑ 1 k x y z 2 \\sum_1^k(3xyz)^2=\\sum_1^k(3\\times 10^3+xyz)^2=\\sum_1^k(3\\times 10^3)^2+2\\times(3\\times 10^3)\\times \\sum_1^kxyz + \\sum_1^kxyz^2 1∑k(3xyz)2=1∑k(3×103+xyz)2=1∑k(3×103)2+2×(3×103)×1∑kxyz+1∑kxyz2
- 上式中, x y z xyz xyz 表示一个3位数, k k k 为 x y z xyz xyz 的个数
- 显然,需要同时计算"数字的个数"、“数字的和” 及 “数字的平方和”
代码
/* hdu 4507 吉哥系列故事——恨7不成妻 数位dp*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MD = 1e9+7;
const int MXN = 25;
struct Ans{ ll x, y, z;}dp[MXN][7][7];
int b[MXN];
ll p[MXN] = {0, 1};
Ans dfs(int m, int r1, int r2, bool ismax){
if(r1 < 0) r1 = r1+7;
if(r2 < 0) r2 = r2+7;
if(m == 0) return (Ans){ r1&&r2, 0, 0};
if(!ismax && ~dp[m][r1][r2].x) return dp[m][r1][r2];
ll x = 0, y = 0, z = 0;
int end = ismax?b[m]:9;
for(ll i = 0; i <= end; ++i){
if(i == 7) continue;
Ans ans = dfs(m-1, r1-i%7, r2-i*p[m]%7, ismax && i == end);
ll pm = p[m]%MD;
x = (x + ans.x)%MD; // 数字个数
y = (y + pm*i*ans.x%MD + ans.y)%MD; // 数字和
z = (z + ans.z)%MD; // 数字平方和
z = (z + pm*i*2%MD*ans.y%MD)%MD;
z = (z + pm*i*i%MD*pm%MD*ans.x%MD)%MD;
}
if(!ismax) dp[m][r1][r2] = (Ans){x, y, z};
return (Ans){x, y, z};
}
ll solve(ll num){
int n = 0;
for(ll i = num; i > 0; i /= 10) b[++n] = i%10;
return dfs(n, 0, 0, true).z;
}
int main(){
int t;
ll L, R;
memset(dp, -1, sizeof dp); // 仅初始化一次
for(int i = 2; i <= 19; ++i) p[i] = 10*p[i-1];
scanf("%d", &t);
while(t--){
scanf("%lld%lld", &L, &R);
printf("%lld\\n", (solve(R)-solve(L-1)+MD)%MD);
}
return 0;
}
以上是关于hdu 4507 恨7不成妻(数位dp)的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 4507 - 吉哥系列故事——恨7不成妻(数位DP,数学)
HDU 4507 吉哥系列故事――恨7不成妻(数位dp&好魔性的一道好题)
HDU 4507 吉哥系列故事――恨7不成妻(数位DP+结构体)