在做算法题时我们经常会遇到这样一句话:
由于答案可能会很大,请你将结果对10^9 + 7取模后再返回

附:为什么很多程序竞赛题目都要求答案对 1e9+7 取模?

  1. 1000000007是一个质数
  2. int32位的最大值为2147483647,所以对于int32位来说1000000007足够大
  3. int64位的最大值为2^63-1,对于1000000007来说它的平方不会在int64中溢出 所以在大数相乘的时候,因为(a∗b)%c=((a%c)∗(b%c))%c,所以相乘时两边都对1000000007取模,再保存在int64里面不会溢出

这句话看上去只要对变量取模就可以了,但实际上取模的时机有一定的讲究,比如新手很容易犯一下两个错误

错误1:用max比较很大数据时,先取模

取mod的时候,如果题目要求你算最大值,并且说由于答案可能很大,输出结果请对1e9+7取,那你千万不能在max函数更新最大值时就取模,这样很可能会出错

比如:题目过程中有四个数据

2e9+7,1e9+6,1e9+5,1e9+4

然后算法中你用max求最大值时,如果先模上1e9+7,那你会得到1e9,1e9+6,1e9+5,1e9+4,并且max函数算出的最大值是1e9+6,可是这四个数的最大值应该是2e9 + 7才对

正确做法:在求max的时候不要先取mod,而是都以long long型数据比大小,最后得到最大值是2e9 + 7,再对它取mod,得到结果是1e9 + 7

例题:1339. 分裂二叉树的最大乘积

错误代码示例

class Solution {public:// 乘积 = 某个节点下所有子节点的和 *(整个树的和 - 某个节点下所有子节点的和)typedef long long LL;LL rmax = 0;LL Total = 0;static const LL mod = 1e9 + 7;// 遍历每个结点,更新最大值LL TreeSum(TreeNode* root) {if (!root) return 0;LL left = TreeSum(root->left);LL right = TreeSum(root->right);LL subsum = left + right + root->val;// 此处先取模,所以数据很大时会出错rmax = max(rmax, (Total - subsum) * subsum % mod);return subsum;}int maxProduct(TreeNode* root) {if (!root) return 0;Total = TreeSum(root);rmax = 0;TreeSum(root);return rmax % mod;}
};


类似题:5752. 子数组最小乘积的最大值

错误2:直到return时才取模

如果让你算1+2+…+n的值(由于答案可能很大,输出结果请对1e9+7取)
n的取值范围是1 ~ 101000010^{10000}1010000

那显然如果你在中间过程中不先取mod,必然会爆数据范围,因为不管是int还是long long甚至是double(最大约1030810^{308}10308)都无法存下这个数据

...
long long res = 0;
for(int i = 1; i <= n ; i ++) {res = res + i; // n巨大,res无法存下这个数据
}return res % (1e9 + 7);

正确做法:在算res的过程中取模

...
long long res = 0;
for(int i = 1; i <= n ; i ++) {res = (res + i) % (1e9 + 7); // n巨大,res无法存下这个数据
}
return res;

有的人会说这不是与错误1矛盾了吗,其实完全不矛盾

  • 错误1是在比较多个很大的数据(不超过long long)
  • 错误2是在维护1个很大的数据,那你先取模和后取模,就没有区别了,因为结果都是一样的

另外有的时候我们经常喜欢用 += 之类的符号,但容易犯以下错误

long long res = 0;
for(int i = 1; i <= n ; i ++) {res += i % (1e9 + 7); // n巨大,res无法存下这个数据
}
return res;

上面的代码实际上并没有对res进行取模,而只是对iii进行取模,当res累加很多数后,是会超过long long,从而出现报错的。所以你要么在下面加一行res %= (1e9 + 7),要么用res = (res + i) % (1e9 + 7);


现在看面试题:剪绳子II这个题,就知道为什么不能用动态规划了,因为取余之后max函数就不能用来比大小

数据较小时下面代码是可以过的,数据大了就不行了,因为不能在max出取模

class Solution {public:// f(n) = max(f(i) * f(n - i)) i:1,..,n-1int cutRope(int number) {// number = 1,2,3时剪一刀,值会变小,所以特殊考虑这几种情况if(number < 2) return 0;if (number == 2) return 1;if (number == 3) return 2;int *f = new int[number + 1];f[1] = 1;f[2] = 2;f[3] = 3;// f(n) n大于3时,表示切若干刀后的最大值for (int i = 4; i <= number; i ++) {int rmax = number;for (int j = 1; j <= i / 2; j ++) {rmax = max(rmax, f[j] * f[i - j]);}f[i] = rmax;}int res = f[number];delete[] f;return res;}
};

错误3:是否真的取模了?

下面的式子取模过程有个坑点:

a[i][j]a[i][j]a[i][j]并没有取模就直接与pre[i][j]pre[i][j]pre[i][j]相乘了(*%是从左往右算的)

res = res % mod + pre[i][j] % mod * a[i][j] % mod;

正确的写法:

res = res % mod + pre[i][j] % mod * (a[i][j] % mod);

写在最后

✨原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下

【C++ 取模mod易错点】由于答案可能会很大,请你将结果对1e9+7取模后再返回相关推荐

  1. 2022年二级注册建筑师《场地设计》考试易错题及答案

    题库来源:优题宝公众号 2022年二级注册建筑师<场地设计>考试易错题及答案,根据最新二级注册建筑师大纲与历年真题汇总编写,包含二级注册建筑师常考重点题型与知识点,有助于考生复习备考二级注 ...

  2. 京东商城百万数据抓取--苏宁易购,淘宝网,京东商城,百万级价格数据海量抓取

    按照惯例先上成果: 过了分割线就是代码 ps:2020.5.14更新了代码:京东商城每周都会更改规则咱们也不能落后 # -*- coding: utf-8 -*- import requests im ...

  3. 求2的n次方对1e9+7的模,n大约为10的100000次方(费马小定理)

    昨天做了一个题,简化题意后就是求2的n次方对1e9+7的模,其中1<=n<=10100000.这个就算用快速幂加大数也会超时,查了之后才知道这类题是对费马小定理的考察. 费马小定理:假如p ...

  4. 为什么对1e9+7取模

    本篇是基于两篇较清晰的解析:为什么是1e9+7和1e9+7取模的易错点的总结 为什么是1e9+7? 1.1e9+7对int来说非常大,通常1e9代表无穷大 int数值的范围是-2147483648 到 ...

  5. # 汇编期末考试复习【选择易错题】

    汇编期末考试复习[选择易错题] (来自南大科院周权来题库--战无不胜的毛泽东思想) 1.用汇编语言编写的程序称为 ( ) A. 汇编程序 B. 源程序 C.可执行文件 D.目标程序 答案:B 注意区分 ...

  6. 爬取三千条数据需要多久_只需几十行代码,Python就能轻松爬取 3000+ 上市公司的信息...

    点击关注"Python学习与数据挖掘" 更多超级干货第一时间推送给你哦!!! 入门爬虫很容易,几行代码就可以,可以说是学习 Python 最简单的途径.刚开始动手写爬虫,你只需要关 ...

  7. C语言下取整下半个方括号,c语言易错知识点总结[工作范文](28页)-原创力文档...

    c语言易错知识点总结 篇一:c语言易错知识 C语言教学中学生容易出错的知识点解析 0引言 C语言是一种很灵活的语言,在程序调试过程中常常会 遇到一些难解决的问题,一般语法错误计算机能检测出来, 而逻辑 ...

  8. Java 取余 (remain),取模 (mod) 的 区别和运算

    范围区别:取模主要是用于计算机术语中.取余则更多是数学概念. 主要的区别在于对负整数进行除法运算时操作不同 那么具体是怎样的不同? 首先需要知道Java中如何取模: Java中用符号%对数字进行取模, ...

  9. matlab 取余(rem)和取模(mod)的区别

    取余(rem)和取模(mod)的区别 Matlab 生成机制 取余:采取fix()函数,向0方向取整 取模:采取floor()函数,向无穷小方向取整 当A,B异号时(其实同号也是这个规律) 取余:结果 ...

最新文章

  1. c语言如何输出整串链表,大神帮我看一下怎么输入输出一个链表,我输入了但是没输出啊...
  2. 在RHEL-4下半小时搭建Sendmail邮件服务器(下)
  3. 相关子查询 与非相关子查询
  4. JMeter性能测试入门
  5. Django(part6)--利用正则的组名进行关键字传参
  6. scala语言示例_var关键字与Scala中的示例
  7. relu函数_ECCV 2020,在视觉任务上大幅超越ReLU的新型激活函数
  8. 深入理解 GraphQL
  9. ArcGis中计算栅格数据指定区域的面积
  10. 【java_wxid项目】【第十五章】【Spring Cloud Skywalking集成】
  11. 计算机专业提升计划范文,民航个人提升计划范文个人职业规划方案.doc
  12. 关于深恶痛绝的file类的delete问题
  13. 华大单片机HC32L130/HC32L136PWM配置
  14. www.ty66.php,韬轩阁
  15. Qt官方示例-虚拟键盘使用
  16. 第六章 Cesium学习入门之添加Geojson数据(dataSource)
  17. Ubuntu下非常给力的下载工具--uget+aria2
  18. mysql.proc is wrong_解决警告:数据库错误Column count of mysql.proc is wrong.
  19. 二进制八进制十进制十六进制及原码反码补码
  20. iOS 利用余弦函数实现卡片浏览工具

热门文章

  1. 处理C++源代码的程序
  2. 城轨车辆段联锁设备采用计算机联锁,车辆段计算机联锁系统简介
  3. HDU3001 Traveling (状压dp+三进制+Tsp问题总结)
  4. IDEA中的Structure模块使用详解
  5. 地震仪器专题-测震仪器发展简史
  6. Incorrect credentials. Request response: 401 Unauthorized
  7. 好的github源码记录(包括人脸...)
  8. Inside LightWave v9
  9. Tire town school learn
  10. GO:交互式命令行工具 survey