模数

HASH 字符串哈希 映射转化

二次信任 提交于 2020-04-06 05:41:49
哈希HASH的本质思想类似于映射、离散化。 哈希,通过给不同字符赋不同的值、并且钦定一个进制K和模数,从而实现一个字符串到一个模意义下的K进制数上。 它的主要目的是判重,用于$DFS$、$BFS$判重(八数码),字符串判断相等、出现等等。 本篇总结字符串哈希以及一些应用例题。 为什要用字符串哈希? 因为取出一个字符串是$O(n)$的,比较一遍又是$O(n)$的,况且要比较两个甚至多个。这就成了$n^2$级别的了。 那我们比较数字怎么就不用这么麻烦呢?因为数字可以直接比较,(虽然不知道内部是怎么实现的,反正比一位一位比较肯定快)所以我们考虑把字符串映射到数字上。 就有了字符串哈希。 通过字符串哈希,只要题目支持预处理,我们可以$O(n)$预处理之后,$O(1)$进行提取,$O(1)$进行判重。 字符串哈希需要什么? 1.字符。初始坐标无所谓。 2.K进制数,通常选择$131$,$13331$,这两个质数冲突几率很小 (不要问我为什么) 。 3.取模数,我用过 $1e9+7$,$998244353$,用$2^{64}$也可以,这里利用自然溢出,一般不会有问题。提一句,$unsigned\space long\space long$做减法,即使算出来应该是负数,会自动加上$2^{64}$,相当于$(a+mod-b)%mod$了。没有问题。 处理hash: 1.预处理$K^{len}$

RSA公钥文件解密密文的原理分析

三世轮回 提交于 2020-03-23 01:05:29
前言   最近在学习RSA加解密过程中遇到一个这样的难题:假设已知publickey公钥文件和加密后的密文flag,如何对其密文进行解密,转换成明文~~ 分析   对于rsa算法的公钥与私钥的产生,我们可以了解到以下产生原理: 公钥与私钥的产生 随机选择两个不同大质数 $p$ 和 $q$,计算 $N = p \times q$ 根据欧拉函数,求得 $r=\varphi (N)=\varphi (p)\varphi (q)=(p-1)(q-1)$ 选择一个小于 $r$ 的整数 $e$,使 $e$ 和 $r$ 互质。并求得 $e$ 关于 $r$ 的模反元素,命名为 $d$,有 $ed\equiv 1 \pmod r$ 将 $p$ 和 $q$ 的记录销毁 此时,$(N,e)$ 是公钥,$(N,d)$ 是私钥。 消息加密 首先需要将消息 $m$ 以一个双方约定好的格式转化为一个小于 $N$,且与 $N$ 互质的整数 $n$。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密: $$ n^{e}\equiv c\pmod N $$ 消息解密 利用密钥 $d$ 进行解密。 $$ c^{d}\equiv n\pmod N $$ 我们可以知道,RSA公钥主要有两个信息:模数(modulus)和指数(exponent),也就是我们所说的N和e

原码,反码与补码理解

故事扮演 提交于 2020-02-13 09:40:21
原码,反码与补码理解 1. 写作目的 平时学习总结的学习笔记,方便自己理解加深印象。同时希望可以帮到正在学习这方面知识的同学,可以相互学习。新手上路请多关照,如果问题还请不吝赐教。 2. 前置知识 字节 → 位 → 二进制数 计算机存储数据使用字节进行存储,机器有32位,64位为一个最小存储单元,1个字节为8位,那么32位机器一个存储单元存储4个字节,64位机器一个存储单元为8个字节。计算机使用二进制来表示数据,1位代表一个二进制数,要么是1,要么是0。 3. 引出原码 既然是数据,那么就有大小,就需要对数值进行运算。我们用真值来表示数据的大小,正负。 十进制:+8 = 二进制:+1000 十进制:-6 = 二进制:-0110 +1000,-0110既是真值,但是计算机在存储数据时没有单独存储数值的正负,而是同样用1,0来存储负,正,那么这就是原码表示。 十进制:+8 = 二进制:01000 十进制:-6 = 二进制:10110 表示是没有问题?但是问题又出现了,那就是如果是同符号运算,我们很好算,如果符号不相同的两个数相加,我们首先要判断哪个数更大,然后相减得到结果,再用大数的符号标注,这样每次算更加麻烦。而且计算机没有设计减法运算,只有加法运算,因为加法运算更加快速。我们如何来实现2个数的减法。下面就是加法转减法的思路: 4. 同余模数 以表盘为例:表盘有12个刻度

C语言基础--结构体对齐,位域,联合体

末鹿安然 提交于 2020-01-10 03:57:53
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数(alignment modulus)。这种对其限制不仅简化了处理器与存储系统之间的接口的硬件设计,而且提高了存储系统的性能。 2 -- 结构体对齐包括两个方面的含义 1)结构体总长度 2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置 3--不同编译器的对其策略 1)Linux沿用的对其策略是2字节的数据类型(例如short)的地址必须是2的倍数,而更大的数据类型(如int,double)的地址必须是4的倍数。 2)Windows对齐要求更要严格些,任何K字节(基本)对象的地址都必须是k的倍数。 4 -- 结构体大小的计算方法和步骤 1)将结构体内所有数据成员的长度值相加,记为sum_a; 2)将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模式的整数倍; 3)将和sum_b向结构体模数对齐,该模数是#pragma pac指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者。结构体的长度应该是该模数的整数倍.

二进制补码

吃可爱长大的小学妹 提交于 2019-12-21 12:44:16
二进制数减法运算,实际上是计算被减数加上模数减去减数的绝对值。 模数:位数能表示的数字数,四位二进制的模为16(0-15)。一位十进制的模为10(0-9)。 模数减去减数的绝对值就是减数的补码,即减数的绝对值按位取反后加1,例如: 1001 —> 0001 —> 1110 —> 1111 上数与 0001 运算后结果溢出为 0000 ,则完成了减法运算。 来源: CSDN 作者: Epimetheus1 链接: https://blog.csdn.net/lotuseaterr/article/details/103642117

c内存对齐--影响php变量占用的内存

只愿长相守 提交于 2019-12-10 13:39:26
当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密。 首先,至少有一点可以肯定,那就是ANSI C保证结构体中各字段在内存中出现的位置是随它们的声明顺序依次递增的,并且第一个字段的首地址等于整个结构体实例的首地址。比如有这样一个结构体: struct vector{ int x,y,z; } s; int *p,*q,*r; struct vector *ps; p = &s.x; q = &s.y; r = &s.z; ps = &s; assert(p < q); assert(p < r); assert(q < r); assert((int*)ps == p); // 上述断言一定不会失败 这时,有朋友可能会问:"标准是否规定相邻字段在内存中也相邻?"。 唔,对不起,ANSI C没有做出保证,你的程序在任何时候都不应该依赖这个假设。那这是否意味着我们永远无法勾勒出一幅更清晰更精确的结构体内存布局图?哦,当然不是。不过先让我们从这个问题中暂时抽身,关注一下另一个重要问题————内存对齐。 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制

[十二省联考2019]骗分过样例

泄露秘密 提交于 2019-12-03 03:02:20
传送门   这道题是个毒瘤题,花费了博主1day独立解决了16个子任务。下面步入正题。    \(\text{subtask 1-3:1_998244353}\)   这个观察数据不难得出要求 \(19^x\bmod 998244353\) ,直接搞即可。注意到可能 \(x\) 非常大,根据费马小定理 \(x^{P-1} \equiv 1 \pmod P\) ,我们需要 读入取模 。    \(\text{subtask 4:1?}\)   观察数据和提示告诉我们:仍然求 \(19^x\) ,只不过模数不知道。发现输出文件的最大值在 \(10^6\) 左右,我们拿第一个输入直接爆搜检验,最后能找出来 \(P=1145141\) 。    \(\text{subtask 5:1?+}\)   这个是前一个的加强版,发现模数在 \(5\times 10^{18}\) 左右,这个不好暴力了。怎么办呢?我把输入的数排了个序,发现有两组输入的 \(x\) 之差为 \(2\) ,于是我找到这两组对应的输出,得到了: \(19^{264708066}\equiv 1996649514996338529 \pmod P\) 和 \(19^{264708068}\equiv 1589589654696467295 \pmod P\) 。也就是说上面的式子乘上 \(19^2\)

luogu P4245 【模板】任意模数NTT MTT

浪子不回头ぞ 提交于 2019-11-27 07:46:44
luogu P4245 【模板】任意模数NTT MTT Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define maxn 1000000 #define M 32768 #define double long double #define ll long long using namespace std; namespace poly{ const double pi=acos(-1); int rev[maxn],l; struct Cpx{ double x,y; Cpx (double t1=0,double t2=0){x=t1,y=t2;} }; Cpx operator+(Cpx a,Cpx b){ return Cpx(a.x+b.x,a.y+b.y);} Cpx operator-(Cpx a,Cpx b){ return Cpx(a.x-b.x, a.y-b.y); } Cpx operator*(Cpx a,Cpx b){ return Cpx(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); } void FFT(Cpx *a,int n,int flag){ for(int i=0;i<n;++i) rev[i]=(rev[i>>1]

任意模数NTT(MTT)

末鹿安然 提交于 2019-11-27 07:45:17
前言 众所周知,NTT有几个经典的模数: 469762049 , 998244353 , 1004535809 469762049,998244353,1004535809 4 6 9 7 6 2 0 4 9 , 9 9 8 2 4 4 3 5 3 , 1 0 0 4 5 3 5 8 0 9 为什么这些模数被称为NTT模数呢?因为他们都是这样一个形式: P = 2 a ∗ X + 1 P=2^a*X+1 P = 2 a ∗ X + 1 为什么要有这样一个条件呢,因为只有这样,才能找到所需的原根 所以对于一般的一个模数 P = 2 a ∗ X + 1 P=2^a*X+1 P = 2 a ∗ X + 1 ,能适用的最大的多项式长度(包括结果)是 2 a 2^a 2 a 有时候, 给出的多项式长度超过限制,我们就不能用裸的NTT了 一般有两种情况: 模数是NTT模数,但是多项式长度略超出限制(比如模数是1004535809,输入多项式长度和>2097152) 模数不是NTT模数,比如模数是1000000007 这个时候任意模数NTT就非常有用了 正文 我们来分析任意模数NTT做法的思路 思路一(P不是很大的时候) 根据分析,我们发现,多项式长度为N、模数为P的时候,多项式乘法的结果每一项的值 0 ≤ x ≤ P 2 N 0\le x\le P^2N 0 ≤ x ≤ P 2 N