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. 【记】创建 VirtualBoxClient COM 对象失败. 应用程序将被中断

    1. 在本地64位win7系统安装VirtualBox完,启动时提示错误 原因:兼容性造成的 按照下图显示修改VirtualBox快捷方式的兼容性 2. 启动虚拟机时,提示 点击弹出框的确定按钮后,接 ...

  2. ZooKeeper Java Example

    A Simple Watch Client Requirements Program Design The Executor Class The DataMonitor Class Complete ...

  3. Java Collection集合概述及其常用方法

    Collection集合概述 Java数组的长度是固定的,为了使程序能够方便地存储和操作数目不固定的一组数据,JDK类库提供了Java集合 与数组不同的是,集合中不能存放基本类型数据,而只能存放对象的 ...

  4. python类型检查和类型转换

    类型检查 type()用来检查值的类型 (整型.浮点型.布尔值.字符串.空值) 该函数会将检查的结果作为返回值返回,可以通过变量来接收函数的返回值 print(type(1)) # <class ...

  5. log日志拦截

    简介 主要记录一下项目中的日志拦截和异常拦截,由于之前公司项目为单体项目,所使用的日志拦截较为简单,只是用拦截器进行前后对日志的拦截,异常拦截直接使用@ExceptionHandler,而现在公司接口 ...

  6. hdu - 4965

    One day, Alice and Bob felt bored again, Bob knows Alice is a girl who loves math and is just learni ...

  7. Prop验证、inheritAttrs、$attrs的用法和坑

    Prop Prop验证 Vue.component('my-component', { props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) pro ...

  8. 2019CSP复赛游记

    Day 0 作为一个初三的小蒟蒻…… 什么算法都不会打…… 做一道LCA+生成树的图论题调了两个小时…… 明日裸考…… Day 1 Morning 买了两个士力架,带了一盒牛奶,准备在考场上食用(这个 ...

  9. python 线程条件

    条件.事件.信号量本质上都是锁,不常用 """ 常用方法: obj,acquire() Obj.release() obj.wait(),创建是阻塞状态,等待obj.no ...

  10. python 封装底层实现原理

    事实上,python封装特性的实现纯属"投机取巧",之所以类对象无法直接调用私有方法和属性,是因为底层实现时,python偷偷改变了它们的名称. python在底层实现时,将它们的 ...