题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507

题目大意:

找到区间 \([L,R]\) 范围内所有满足如下条件的数的 平方和

  • 不包含‘7’;
  • 不能被 7 整除;
  • 各位之和不能被 7 整除。

注意:求的是满足条件的数的 平方和

解题思路:

使用 数位DP 尽情求解。

但是因为这里求的是满足要求的元素的平方和,而不是元素的个数。

所以我们不能简单地开long long来存放结果,

而是开一个结构体来存放结果,结构体中需要包含三个元素:

  • 满足要求的元素个数(用 cnt 表示);
  • 满足要求的元素的和(用 sum 表示);
  • 满足要求的元素的平方和(用 sum2 表示)

定义状态 \(f[pos][pre][ts]\) 表示:

  • 当前在第 \(pos\) 位;
  • 前一位(即第 \(pos+1\) 位)放置的数 mod 7为 \(pre\)
  • 前面所有位上的数的和 mod 7 的结果为 \(ts\)

时对应的信息(包括元素个数、和、平方和)。

那么如何获得状态转移方程呢?

每次查找的数字的前几位都是一样的,比如对于三位数:

\[abc
\]

假设第一位枚举了2;即

\[2|b|c
\]

那么之后枚举到的数字就是 \(200+x\) 。

如果 \(200\) - \(300\) 之间只有 \(231\) ,\(230\) 和 \(233\) 满足条件,那么 \(200\) - \(300\) 之间的数的平方和就为

\[230^2+231^2+233^2
\]

也就等于

\[(200+30)^2+(200+31)^2+(200+33)^2
\]

展开后得到:

\[3 \times 200^2+2 \times 200 \times (30+31+33)+(30^2+31^2+3^32)
\]

并且我们可以据此得到状态转移了。

(上述思路来自 Ender的博客 ,不过他的公式推到错了,多乘了一个3,所以还是看我的计算公式即可)

实现的代码如下:

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007LL;
struct Node {
long long cnt; // 数量
long long sum; // 和
long long sum2; // 平方和
Node () {};
Node (long long _cnt, long long _sum, long long _sum2) {
cnt = _cnt; sum = _sum; sum2 = _sum2;
}
} f[22][7][7];
int a[22];
bool vis[22][7][7];
long long pow10[22];
void init() {
memset(vis, 0, sizeof(vis));
pow10[0] = 1;
for (int i = 1; i < 22; i ++) pow10[i] = pow10[i-1] * 10 % MOD;
}
Node dfs(int pos, int pre, int ts, bool limit) {
if (pos < 0) {
int cnt = 1;
if (pre == 0) cnt = 0; // 不能被7整除
if (ts == 0) cnt = 0; // 所有数位的和不能被7整除
return Node(cnt, 0, 0);
}
if (!limit && vis[pos][pre][ts]) return f[pos][pre][ts];
int up = limit ? a[pos] : 9;
Node res = Node(0, 0, 0);
for (int i = 0; i <= up; i ++) {
if (i == 7) continue; // 不能包含7
Node tmp = dfs(pos-1, (pre*10+i)%7, (ts+i)%7, limit && i==up);
long long tmp_cnt = tmp.cnt;
long long tmp_sum = tmp.sum;
long long tmp_sum2 = tmp.sum2;
long long t = pow10[pos] * i % MOD;
long long now_sum = (t * tmp_cnt + tmp_sum) % MOD;
long long now_sum2 = (tmp_cnt * t % MOD * t % MOD + 2LL * t % MOD * tmp_sum % MOD + tmp_sum2) % MOD;
res.cnt = (res.cnt + tmp_cnt) % MOD;
res.sum = (res.sum + now_sum) % MOD;
res.sum2 = (res.sum2 + now_sum2) % MOD;
}
if (!limit && !vis[pos][pre][ts]) {
vis[pos][pre][ts] = true;
f[pos][pre][ts] = res;
}
return res;
}
long long get_num(long long x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, 0, true).sum2;
}
int T;
long long L, R;
int main() {
init();
scanf("%d", &T);
while (T --) {
scanf("%lld%lld", &L, &R);
printf("%lld\n", (get_num(R) - get_num(L-1) + MOD) % MOD);
}
return 0;
}

HDU4507 吉哥系列故事——恨7不成妻 题解 数位DP的更多相关文章

  1. 2018.09.27 hdu4507吉哥系列故事——恨7不成妻(数位dp)

    传送门 一道比较综合的数位dp. 维护三个值:[L,R][L,R][L,R] 区间中与7无关的数的数量,与7无关的数之和,与7无关的数的的平方和. 然后可以用第一个值推第二个,第一个和第二个值推第三个 ...

  2. 吉哥系列故事——恨7不成妻(数位dp)

    吉哥系列故事--恨7不成妻 传送门 Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥 ...

  3. HDU - 4507 - 吉哥系列故事——恨7不成妻(数位DP,数学)

    链接: https://vjudge.net/problem/HDU-4507 题意: 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都 ...

  4. hdu_4507_吉哥系列故事——恨7不成妻(鬼畜数位DP)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题意:中文,不解释,注意的是求的是合法数字的平方和,即(a+b+c+……)^2 题解:数位DP, ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题目大意:如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关 1.整数中某一位是7: ...

  6. HDU 4507 吉哥系列故事——恨7不成妻 (数位DP)

    题意: 如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关: 1.整数中某一位是7: 2.整数的每一位加起来的和是7的整数倍: 3.这个整数是7的整数倍: 给定一个区间[L,R],问在此区 ...

  7. [HDU4507]吉哥系列故事——恨7不成妻

    [HDU4507]吉哥系列故事--恨7不成妻 试题描述 单身!依然单身!吉哥依然单身!DS级码农吉哥依然单身!所以,他生平最恨情人节,不管是214还是77,他都讨厌!吉哥观察了214和77这两个数,发 ...

  8. hdu4507吉哥系列故事——恨7不成妻 (数位dp)

    Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...

  9. HDU-4507 吉哥系列故事——恨7不成妻 数位DP

    题意:给定区间[L, R]求区间内与7无关数的平方和.一个数当满足三个规则之一则认为与7有关:1.整数中某一位是7:2.整数的每一位加起来的和是7的整数倍:3.这个整数是7的整数倍: 分析:初看起来确 ...

随机推荐

  1. @bzoj - 4378@ [POI2015] Logistyka

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 维护一个长度为 n 的序列,一开始都是 0,支持以下两种操作: ...

  2. 带你进入 Activiti 工作流的世界

    Activiti 是一个针对企业用户.开发人员 .系统管理员的轻量级工作流业务管理平台,其核心是使用 java 开发的快速 . 稳定的 BPMN2.0 流程引擎 .它可以与 spring 完美集成. ...

  3. 如何利用aop的环绕消息处理log, 以及各种坑的记录

    如何利用aop的环绕消息处理log, 以及各种坑的记录 本文链接: https://www.cnblogs.com/zizaiwuyou/p/11667423.html 因为项目里有很多地方要打log ...

  4. hdu 1045 Fire Net(dfs)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  5. hibernate无限递归问题

    项目异常如下: 2018-01-26 17:12:38.162 WARN 3128 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionReso ...

  6. 详解PhpStudy集成环境升级MySQL数据库版本

    http://phpstudy.php.cn/jishu-php-2967.html phpstudy里没有地方可以设置mysql数据库,很多人都疑惑在phpstudy里怎么升级mysql数据库版本, ...

  7. Python--day41--线程池--python标准模块concurrent.futures

    1,线程池代码示例:(注:进程池的话只要将以下代码中的ThreadPoolExecutor替换成ProcessPoolExecutor即可,这里不演示) import time from concur ...

  8. Python--day40--复习和回调函数实例

  9. 2018-8-10-UWP-分享用那个图标

    title author date CreateTime categories UWP 分享用那个图标 lindexi 2018-08-10 19:16:52 +0800 2018-2-13 17:2 ...

  10. Python--day37--进程锁

    进程锁的示意图: 锁.py: #锁 #火车票 import json import time from multiprocessing import Process from multiprocess ...