Nov 11,2019 ~ Nov 17,2019

Algorithm

本周来介绍快速求一个数字n次方的余数。

理论基础

我们先定义运算$ x \bmod p = r \(与\) x \equiv r \pmod p \(的含义是一样的。若\) p = 5 $,则可以将所有整数划分到5个不相交的集合里,具体如下:

\[\left\{\begin{matrix}
& \{\dots -10, -5, 0, 5, 10 \dots \} \bmod 5 = 0 & \\
& \{\dots -9, -4, 1, 6, 11 \dots \} \bmod 5 = 1 & \\
& \{\dots -8, -3, 2, 7, 12 \dots \} \bmod 5 = 2 & \\
& \{\dots -7, -2, 3, 8, 13 \dots \} \bmod 5 = 3 & \\
& \{\dots -6, -1, 4, 9, 14 \dots \} \bmod 5 = 4 & \\
\end{matrix}\right.
\]

可能有人不懂为什么\(-4 \bmod 5 = 1\),我来解释一下,因为$ -4 = 5 \times (-1) + 1 \(,故\) -4 \div 5 = -0.8 = -1 \cdots 1 \(。因此\)-4 \bmod 5 = 1$

那么根据上面的描述,就可以将数之间的运算通过取余映射在有限个集合内。那么,有如下两条基本性质,可以更加方便我们进行求解

  1. 若存在 $ a \equiv b \pmod p, c \equiv d \pmod p $ ,则 $ a+c \equiv b+d \pmod p $ 。
  2. 若存在 $ a \equiv b \pmod p, c \equiv d \pmod p $ ,则 $ ac \equiv bd \pmod p $

通过这样的性质就很容易求解一个大数的对某个数字取余的结果。以计算\((2^{32} + 5)\bmod 7 = ?\)为例

  1. $ 2 \bmod 7 = 2 $
  2. $ 2^2 \bmod 7 = (2 \times 2) \bmod 7 = 4$
  3. $ 2^4 \bmod 7 = (2^2 \times 2^2) \bmod 7 = 4 \times 4 \bmod 7 = 2 $
  4. $ 2^8 \bmod 7 = {2^4 \times 2^4} \bmod 7 = [(2^4 \bmod 7) \times (2^4 \bmod 7)] \bmod 7 = (2 \times 2) \bmod 7 = 4 $
  5. $ 2^{16} \bmod 7 = {2^8 \times 2^8} \bmod 7 = [(2^8 \bmod 7) \times (2^8 \bmod 7)] \bmod 7 = (4 \times 4) \bmod 7 = 2 $
  6. $ 2^{32} \bmod 7 = (2^{16} \times 2^{16}) \bmod 7 = [(2^{16} \bmod 7) \times (2^{16} \bmod 7)] \bmod 7 = (2 \times 2) \bmod 7 = 4 $
  7. $ (2^{32}+5) \bmod 7 = [(2^{32} \bmod 7) + (5 \bmod 7)] \bmod 7 = (4 + 5) \bmod 7 = 2 $

具体实现

设问题为:求解$ a^x \bmod b = ? \(。因此问题的关键在于如何分解\)x$,具体有两种基本思路,分别是按照210进行分解。当然也可以按照其他数进行分解,但实现起来较复杂。

  1. 按数字2来分解,分解的基本原理如下:

\[\begin{cases}
& x = x // 2 + x // 2,\quad a^x = a^{x//2} \times a^{x//2} \quad \text{ if } x \bmod 2 = 0 \\
& x = x // 2 + x // 2 + 1,\quad a^x = a^{x//2} \times a^{x//2} \times a \quad \text{ if } x \bmod 2 = 1
\end{cases}
\]

根据上述公式不难写出代码:

def my_mod(a, x, b):
if x == 1:
return a % b
else:
tmp = my_mod(a, x//2, b)
if x % 2 == 0:
return ( tmp * tmp ) % b
else:
return ( tmp * tmp * my_mod(a, 1, b) ) % b
  1. 按数字10来分解,分解的基本原理如下,因为是递归的,为了方便理解,使用数字123为例:

    $ 123 = (1 \times 10 + 2) \times 10 + 3 \(
    \) a^{123} = ({3^1} ** 3^{10} \times 3^2 ) ** 3^{10} \times 3^3 $

    实现代码如下:
def my_mod(a, x, b):
def cal_mod(a, b):
L = []
for i in range(11):
L.append( (a**i) % b )
return L def recursive(x):
if 0 <= x <= 9:
return L[x]
else:
return ( recursive(x//10) ** L[10] * recursive(x%10) ) % b if 0 <= x <= 10:
return (a**x) % b
L = cal_mod(a, b)
return recursive(x)

Review

Why is the gets function so dangerous that it should not be used?

在一个比较早的代码时,运行总会出错,后面通过查找资料,发现是gets函数的问题。

当我查阅gets函数时发现,在DESCRIPTION部分直接写道Never use this function.

在阅读了一些关于gets英文文章后,我明白了为什么gets会带来问题。

简单地说,带来隐患的根源在于gets函数不会控制读入的量,而只是以\n\0作为读入的终止。例如下面这个代码:

#include<stdio.h>

int main()
{
char str1[] = "hello";
char str2[] = "world";
char *str = gets(str1);
return 0;
}

程序开始运行后,输入任意个字符,点击回车将会直接带来段错误从而终结程序。

Tips

根据上述的描述,凡要涉及到gets函数,都可以使用fgets函数进行代替

fgets函数原型如下

char *fgets(char *s, int size, FILE *stream);

从标准输入的读取方法如下:

char buffer[100];
while (fgets(buffer, sizeof(buffer), stdin))
{
// operations
}

Share

本周分享一个关于vim配置的项目——VimPlus

不少vim用户都喜欢安装或多或少的插件以增强原生vim的功能,但不少新手第一次安装插件时可能会遇到某些问题,同时也未必会一次安装配置好需要的插件。而这个项目就是为了方便新手可以通过简单的运行命令就可以安装许多常用的插件,进而配置出一个像IDE似的vim。

其中可以一键安装的插件包括vim-plugYou Complete Me

目前项目的作者的维护也比较及时。希望未来可以越做越好!

更多内容可去上述项目链接中进行查看。

(注:我与作者没有任何联系,只是发现了这个项目并且个人尝试后觉得不错,所以分享在这里)

ARTS Week 3的更多相关文章

  1. KDE声音服务器 arts

    KDE声音服务器 arts arts介绍arts是KDE的核心声音系统,支持多音频流.全双工.网络声音请求.ALSA与OSS驱动后端.JACK声音服务器后端等扩展,它既是声音服务器,也 提供一套音频软 ...

  2. 【ARTS】01_21_左耳听风-201900401~201900407

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  3. 【ARTS】01_20_左耳听风-20190325~20190331

    zz## ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 ...

  4. 【ARTS】01_19_左耳听风-20190318~20190324

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  5. 【ARTS】01_18_左耳听风-20190311~20190317

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  6. 【ARTS】01_17_左耳听风-20190304~20190310

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  7. 【ARTS】01_16_左耳听风-20190225~20190303

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  8. 【ARTS】01_15_左耳听风-20190218~20190224

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  9. 【ARTS】01_14_左耳听风-20190211~20190217

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  10. 【ARTS】01_13_左耳听风-20190204~20190210

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

随机推荐

  1. java基础之----redi分布式锁

    最近项目中,用到了redis分布式锁,使用过程有些心得,所以希望分享给大家. 首先我们意识里要知道分布锁有哪些? 分布式锁一般分三种,基于数据库的乐观锁,基于redis的分布式锁,基于zookeper ...

  2. PHP高级程序员必看知识点:目录大全(不定期更新)

    面试题系列: 分享一波腾讯PHP面试题 2019年PHP最新面试题(含答案) Redis 高级面试题 学会这些还怕进不了大厂? 阿里面试官三年经验PHP程序员知识点汇总,学会你就是下一个阿里人! ph ...

  3. CMS总结

    过程 初始标记 从roots(例如:thread stack引用的对象,static对象),新生代对象,标记直接引用的老年代对象. 并发标记 利用初始标记阶段标记的对象,递归标记整个老年代. 该阶段与 ...

  4. 【转】ArcGIS Server 10.1 动态图层—更改风格

    在 ArcGIS Server REST API中我们可以通过向Graphicslayer中添加临时图元的方法来完成对显示结果的渲染:如果仅仅是更改原有地图服务显示风格,在ArcGIS10.1下使用动 ...

  5. C#调用Matlab生成的Dll

    问题描述:最近开发需要调用matlab生成的DLL,在New MWNumericArray 对象的时候报错,提示未将对象引用到对象的实例. 问题分析:因为MWArray.dll是Matlab提供的DL ...

  6. 关于django中的get_or_create方法的坑

    最近在项目中发现了这样的一个坑,那就是我们的需求是不能添加一个相同的对象到数据库中,就通过某些字段的值组合成唯一值到数据库中去查找数据,如果没有找到对象,那就创建一条新的数据库记录,而刚好django ...

  7. 曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  8. Django 添加 app

    一.创建Django项目的时候添加 二.在终端创建app python manage.py startapp app名称 运行完命令后,要在settings.py文件中,添加配置文件

  9. 关于C++读入数字按位取出与进制转换问题

    这一片博客我就不写具体的一个题了,只是总结一种典型问题——读入数字按位取出. 就拿数字12345举例吧. 是首先,我们要取出个位.这样取出: 12345/1=12345 12345%10=5.    ...

  10. 18年第一弹射 和网络有关; 艾曲塞嗯诶系列篇 two

    35: 华为AR G3系列路由器可以通过FTP和TFTP更新系统文件,AR G3系列路由器可以作为FTP Client , FTP Server ,TFTP Client 36: 两台路由器间通过串口 ...