题目链接: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. larave5.6 将Excel文件数据导入数据库代码实例

    <?php namespace App\Admin\Controllers; use App\AdminUser; use Illuminate\Http\Request; use Excel; ...

  2. 本地测试读取redis和普通文件缓存的速度,redis慢一倍?

    重新测试了,换成了Linux服务器,php5.6,512内存.连续读取1千次不同的文件(每个文件41KB),redis也是1千个不同的key,文件缓存还是比redis快! 但是,但是,后来我换成连续读 ...

  3. 1、Dapper介绍

    1.Dapper是一个轻量级的O/R框架,性能强劲,支持原生sql与模型对象混合写法,通过DapperExtension插件可以实现纯模型的操作(零Sql)语句. 2.创建VS 项目,添加相关的依赖包 ...

  4. 禁用GPU版本TensorFlow,切换到CPU版本TensorFlow。

    #禁用gpu版本TensorFlow,因为CUDA号码从0开始,这里直接让CUDA使用-1的GPU,自然就无法使用gpu了. 代码前面加入: import osos.environ["CUD ...

  5. H3C PPP MP配置示例一

  6. uni-app学习记录01-pages配置项

    { // 每个页面都需要在pages里面去声明配置 "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/coll ...

  7. Python--day64--找到作者关联的所有书籍对象、ORM多对多关联查询的原理

    找到当前作者关联的所有书籍对象: ORM多对多关联查询的原理: 编辑作者:

  8. H3C 配置NAPT

  9. 使用原生JS封装一个动画函数

    最近一直在忙项目,很少有时间回顾之前的知识,今天刚好要做一个轮播,因为对兼容性有一定的要求,使用了各种插件和库中的轮播,效果都不是很理想,一怒之下,使用原生JS封装了一个轮播组件,其中重要的功能就是一 ...

  10. java 反射和泛型-反射来获取泛型信息

    通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...