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{0123456}
  • s t a t e 2 ∈ { 0 、 1 、 2 、 3 、 4 、 5 、 6 } state2\\in \\{0、1、2、3、4、5、6\\} state2{0123456}
  • 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 1k(3xyz)2=1k(3×103+xyz)2=1k(3×103)2+2×(3×103)×1kxyz+1kxyz2
  • 上式中, 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&好魔性的一道好题)

HDU4507 吉哥系列故事——恨7不成妻 题解 数位DP

HDU 4507 吉哥系列故事――恨7不成妻(数位DP+结构体)

hdu-4507 吉哥系列故事——恨7不成妻 数位DP 状态转移分析/极限取模

[HDU 4507] 吉哥系列故事――恨7不成妻