泛型编程与 OI——modint
博客链接。
在 OI 中,有大量的题目要求对一些数字取模,这便是本文写作的背景。
背景介绍
这些题目要么是因为答案太大,不方便输出结果,例如许多计数 dp;要么是因为答案是浮点数,出题人不愿意写一个确定精度的 Special Judge,例如很多期望概率题;要么是因为这道题目直接考察了模的性质和运用,比如大量的 998244353 类的多项式题目。
过去的做法
在这种要求之下,取模运算就成为了编程中不可缺少的一部分。下面以式子 \(\texttt{ans}=(x+y+z)\times u\) 为例介绍几种写法。
第一种 直接取模
这种方法是直接取模,简单直接,清晰明了。
constexpr int p=998244353;
int ans=1ll*(((x+y)%p+z)%p)*u%p;
但是这种方法有着严重的缺陷,一是容易忘记大括号,二是容易中间运算时搞错运算顺序、忘记取模,三是式子太长、括号太多、不易检验。
因此,不推荐运用这种方法。
第二种 函数取模
这种方法有效地解决了直接取模的忘记取模的漏洞。
constexpr int p=998244353;
int add(int a,int b){
return a+b>=p?a+b-p:a+b;
}
int sub(int a,int b){
return a<b?a-b+p:a-b;
}
int mul(int a,int b){
return 1ll*a*b%p;
}
int ans=mul(add(add(x,y),z),u);
但是,这种写法的式子依旧太长,不易检验,并且如果编译器没有任何优化(现在不存在这种情况了)的话,大量的函数调用将会耗费不少的时间。并且如果要对多个模数取模,则需要写多个函数,显得代码冗长。
泛型编程
考虑到函数取模的优点,我们不妨通过类的运算符重载来进一步优化 add
等函数。
同时为了解决多个模数的问题,我们考虑泛型编程,将模数直接包含在类型中。
template<typename T,const T p>
class modint{
private:
T v;
public:
modint(){}
modint(const T& x){assert(0<=x&&x<p);v=x;}
modint operator+(const modint& a)const{
return v+a.v>=p?v+a.v-p:v+a.v;
}
modint operator-(const modint& a)const{
return v<a.v?v-a.v+p:v-a.v;
}
modint operator*(const modint& a)const{
return 1ll*v*a.v%p;
}
T operator()(void)const{
return v;
}
};
modint<int,998244353> x(),y(),z(),u();
modint<int,998244353> ans=(x+y+z)*u;
这样使用的时候,一方面减少了心智负担,不用操心运算时忘记取模;另一方面采取了常数更小的加减法操作,运算更快。
唯一的缺点就是类型名难写,但是模数个数少的时候可以缩写,即写成:
typedef modint<int,998244353> modInt1;
这样就解决了类型名长的缺点。
泛型编程与 OI——modint的更多相关文章
- C++泛型编程:template模板
泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础. 所谓template,是针对“一个或多个尚未明确的类型”所编写的函数或类. 使用template时,可以显示的或隐示的将 ...
- 再见,OI
你好,NOIP 2015年9月1日 正式成为了福建省莆田一中的一名高一成员 后来学校搞了选修 大家都很激动 因为自己的兴趣和特长能够得到发挥了(或者说能逃课或者看好多电影) 发现选修提供的选项中有好几 ...
- C语言的泛型编程
1 问题引入 首先引入一个问题,实现一个泛型的swap函数,分别使用C++和C实现. 2 C++的泛型 C++有良好的泛型编程机制,所以我很快就写出了C++版的泛型swap函数. template&l ...
- 告别我的OI生涯
本文章写于2008年12月15日. 随着2008noip的结束,我也结束了我的OI生涯. 信息竞赛也许是从小到大让我最最努力的一件事.我记得参加2006noip初赛前,每天中午为了上信息课都吃不上中午 ...
- 收集一些关于OI/ACM的奇怪的东西……
一.代码: 1.求逆元(原理貌似就是拓展欧几里得,要求MOD是素数): int inv(int a) { if(a == 1) return 1; return ((MOD - MOD / a) * ...
- c++ 泛型编程及模板学习
泛型编程,英文叫做Generic programming 可以理解为,具有通用意义的.普适性的,编程. 比如,你要实现一个函数去比较两个数值的大小,数值可能是int或者string.初次尝试,我们直观 ...
- C++学习笔记26:泛型编程概念
一.什么是泛型编程? 泛型就是通用的型式 编写不依赖数据对象型式的代码就是泛型编程 二.为什么需要泛型编程? 函数重载,相似类定义与型式兼容性 例如:设计函数,求两个数据对象的较小值 //未明确规定参 ...
- C++ STL泛型编程——在ACM中的运用
学习过C++的朋友们应该对STL和泛型编程这两个名词不会陌生.两者之间的关系不言而喻,泛型编程的思想促使了STL的诞生,而STL则很好地体现了泛型编程这种思想.这次想简单说一下STL在ACM中的一些应 ...
- 继续OI
NOIP2016于2016.11.20日12:00正式结束. 我作为oi的生涯 或许会结束? 或者继续? 然而前途依然迷茫,我是否应该继?或是放弃? 距离省选还有3~4个月,我该何去何从? 虽然已经经 ...
随机推荐
- 【LeetCode】894. All Possible Full Binary Trees 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- Lotus and Horticulture
Lotus and Horticulture Accepts: 91 Submissions: 641 Time Limit: 4000/2000 MS (Java/Others) Memory Li ...
- 警惕!PHP、Node、Ruby 和 Python 应用,漏洞还没结束!
12 月 10 日凌晨,Apache 开源项目 Log4j2 的远程代码执行漏洞细节被公开,作为当前全球使用最广泛的 java 日志框架之一.该漏洞影响着很多全球使用量前列的开源组件,如 Apache ...
- 亲测:三个值得练手的Java实战项目
测试奇谭,BUG不见. 大家好,我是谭叔. 一提到编码,很多小伙伴便感到头疼,特别是半路转行的小伙伴或者没有系统学习过计算机基础的小伙伴. 对于想学而不知道怎么学的小伙伴,我可以分享下我的策略: 刷一 ...
- Java 泛型通配符 T,E,K,V,?
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被 ...
- Towards Evaluating the Robustness of Neural Networks
目录 概 主要内容 基本的概念 目标函数 如何选择c 如何应对Box约束 attack attack attack Nicholas Carlini, David Wagner, Towards Ev ...
- CS5262设计DP转HDMI 4K60HZ +VGA 1080P方案芯片
CS5262是一款带嵌入式MCU的4通道DisplayPort1.4到HDMI2.0/VGA转换器芯片,设计用于将DP1.4信号源连接到HDMI2.0接收器.CS5262集成了DP1.4兼容接收机和H ...
- 1.spring系列之优雅的实现接口统一返回
好处 现在公司开发基本上都是以前后分离模式为主,所以要有个统一的数据格式,这样有什么好处呢? 能够提高前后端对接的效率(特别重要) 代码更加优雅和简洁 对于前端和后端维护更方便容易 实现(直接上代码) ...
- BUG—Nuget包版本不一致导致程序行为与预期不符
注:本文收录于<Bug集锦>,请点击此处查看全文目录 BUG起因 先介绍一下背景: 数周前的一个极其平常的下午,完成了本次迭代的开发工作,发布到QA提测,然后开始摸鱼.没几分钟,测试就来找 ...
- SpringBoot 原理分析、监控、项目部署
目录 SpringBoot 监控 概述 使用 SpringBoot Admin 概述 使用 SpringBoot 项目部署 SpringBoot 监控 概述 SpringBoot 自带监控功能 Act ...