初等数论
素数
大家都会,略过
就是
的线性筛
素数定理
唯一分解定理
略过
威尔逊定理
为素数,则 同时,它的逆定理也成立。
费马小定理
为素数, 为正整数, 与 互质,则 ( ) 。
欧拉小定理
mod ,( 与 互质)
欧几里得算法
扩展欧几里得算法
求解形如ax+by=gcd(a,b)方程的一组解。
当b=0时,原方程的解就是x=1,y=0。
假设
有解。
所以我们也找到了原方程的一组解,按照欧几里得算法那样递归求解即可
裴蜀定理
若
是整数,且
,那么对于任意的整数
,
都一定是d的倍数,特别地,一定存在整数
,使
成立。
推广:n个整数,
为n个整数,
是它们的最大公约数,那么存在整数
使得
逆元
递推
求单个数的逆元
中国剩余定理
很显然略过
Baby Step Giant Step(BSGS)
用于求解方程
(P为质数)
令
原式转化为
(
)
即
左边枚举
丢进
表
右边枚举
去与
表对应
扩展BSGS
显而易见的,BSGS需要求逆元,也就是要求
也就是说,
时,不能用BSGS。
对于方程
,假设
,若
不成立(特殊条件
暂不考虑),方程无解。
改写原方程
后面任然用BSGS
大数分解
大数分解:将n分解为质因数的积的形式(n可能很大,O(√n)算法无法完成)
大数分解给人的第一感觉:玄学
算法:
1.找到一个数p,使得
,将
分解为
与
;
2.如果
或
不是素数,继续递归;
3.如果是素数,记录并退出。
大数分解有两个关键:
第一个是如何判定一个数是不是素数。
这里我们用到了
算法:
设我们要判定的数是
,如果存在一个底数
,使得
不成立,那么
肯定不是质数。
随机几次,出错率就比较低了。
为了使出错率更低,还有二次探测的方法。
如果
是奇素数,则
的解为
或
。
对于奇素数
(
为奇数),一般对
,
,…,
进行二次探测。
另一个是如何找
使得
:
1.找到一个数
;
2.通过某种玄学手段得到与
对应的一个数
;
3.判断
是否能整除
,即
是否大于1;
4.如果大于
,
即为所求,否则
作为一个新的
,继续重复上述过程。
实际使用中,一般用如下公式进行推导:
,其中c为随机常数。这个公式能保证在形成环之前,
基本不会相等。
如何判断是否形成环:标记i位于1,标记j位于2,标记i随着过程不断++,碰到标记j后,标记j的位置*2,并记录当前标记i处的值,这样能保证当j-i>环的大小时,一定能找到环。碰到环了就直接退出,换一个随机常数再找。
一些例题
压惊水题
给定一个长度为n的数组,求ai|aj这样的数对(i,j)有多少个?
其实只要枚举每一个数组中的数及其他们的倍数就行了
BZOJ1477 青蛙的约会
exgcd裸题
剩下扩欧好了
#include<bits/stdc++.h>
using namespace std;
long long x,b,a,y,m,n,l,t,d,ans;
int ex_gcd(long long &x,long long &y,long long a,long long b)
{
if(!b) return x=d/a,y=0;
ex_gcd(x,y,b,a%b),t=x;
return x=y,y=t-a/b*y;
}
int main()
{
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
d=(y-x+l)%l;
a=(m-n+l)%l;
b=l;
long long a1=a,b1=b;
while(b1)
{
t=b1;
b1=a1%b1;
a1=t;
}
if(d%a1==0)
{
ex_gcd(ans,y,a,b);
while(ans<0) ans=(ans+l)%l;
printf("%lld",ans%l);
}
else
printf("Impossible");
return 0;
}
BZOJ2257 瓶子和饮料
给定n个瓶子的容量,选出其中k个,最大化k个瓶子之间无度量所能表达的最小体积。
实际上是答案就是
个瓶子体积的
枚举所有的质因子判断一下是否出现次数超过
即可
https://blog.csdn.net/a1035719430/article/details/81055790
BZOJ2818 GCD
当然是莫比乌斯反演啦
好啦,N这么小怎么可能毒瘤莫比乌斯呢
莫比乌斯可以优化我们这题的做法做到更优
其实我们只要枚举
,然后
可以等价到
也就是我们只要在
之间直接统计答案即可
BZOJ4173数学
这题还真是鬼畜….
我们也可以鬼畜,打表出答案
我们考虑证明
第二个
中的(
)等价于
将原式转化
那么原式答案就为
其实打表是很好的,只要打表后面那个 就可以愉快AC了
bzoj3122随机数生成器
如果高中数列你学的没问题你可以很轻松的写出通项公式
蓝后你就可以得到形如:
的式子了
BSGS!
组合数学
加法原理&乘法原理
略过
排列组合
公式略过
经典例题
某保密装置须同时使用若干把不同的钥匙才能打开。现有7人,每人持若干钥匙。须4人到场,所备钥匙才能开锁。问①至少有多少把不同的钥匙?②每人至少持几把钥匙?
解析:
①每3人至少缺1把钥匙,且每3人所缺钥匙不同。故至少共有C(7,3)=35把不同的钥匙。
② 任一人对于其他6人中的每3人,都至少有1把钥匙与之相配才能开锁。故每人至少持C(6,3)=20把不同的钥匙。
可重复的排列
如果S是一个多重集,它有K个不同的类型元素,各元素分别为 个,那么,S的全排列个数为
可重复的组合
设S是一个具有k种类型元素的多重集,每种元素均具有无限的重复数.则S的r-组合数为C(r+k-1,r).
例题简单略过
二项式定理
对照杨辉三角理解
特殊情况:
组合数性质
⑴
显然
⑵
显然
⑶
略微证明:
由
则
证毕
⑷
显然
⑸
一句话证明:将
带入二项式定理
⑹
一句话证明:将
带入二项式定理
⑺
显然
⑻
一句话证明:用
将每一项的左边(含m的组合数)变换一下即转化为前一个式子
⑼
左右展开即可
⑽
简要证明:
首先由前面我们可以知道
和
式子2告诉我们前面两项相等,式子1告诉我们两项都是
⑾
证明:将k的每一项通过
换一下
变换得
由
得
原式
⑿
证明:
将⑼
左右同乘
再化简
得
然后原始就好处理了。
原式
⒀
证明:
对于⑻
令
即可得到原式
⒁
一句话证明:二项式定理拆开,中间的部分都包括因子n
组合数取模
直接上杨辉三角
,p是素数(比n和m大)
预处理阶乘以及阶乘的逆元
且为素数。
定理
C(n,m)=C(n%p,m%p)*C(n/p,m/p)
只需要递归处理
\一部分即可。
定理的证明:
就是
中
项的系数
设
,
有
所以
项的系数就是
对于不同的
,我们可以用中国剩余定理定理解决
现在主要的问题就是对
取模。
将
表示为
,就可以解决问题了。
Catalan数
非线性递推关系
.
线性递推关系
组合式
Fibonacci数
性质:
均可通过数学归纳法证明
一一对应
将一个复杂问题转化为另一个对应的简单问题,使得两者的所有情况一一对应;或者将一个不熟悉、冗余的问题转化为一个熟悉、清晰的问题。这是我们解题的重要思路和思考方法
prufer编码
假定已知的n个顶点标志为1,2,…,n,假定T是其中的一棵树,叶节点中有标号最小者。设为a1,a1的邻接点为b1,从T中消去点a1和边(a1,b1)。再从余下的树T1中寻找标号最小的叶节点,设为a2,a2的邻接点为b2,从从T1中消去点a2和边(a2,b2)。如此步骤n-2次,直到最后剩下一条边为止。于是一棵树T对应一序列{b1,b2,…,bn-2},这些数是1~n中的数,并且允许重复。
反过来从b1,b2…bn-2可以恢复树T本身
在序列(1)中找出第一个不出现在序列(2)中的数,这个数显然便是a1,同时形成边(a1,b1),并从(1)中消去a1,从(2)中消去b1。在余下的(1)和(2)中继续以上的步骤n-2次,直到序列(2)为空集为止。这时序列(1)中剩下的两个数x,y,边(x,y)就是树T的最后一条边
Prufer编码指的就是序列
Prufer编码的一个重要性质:一个节点的度数为d,那么它在Prufer序列中出现的次数为d-1。
容斥原理
[
定理]
拓展
一般形式
应用
证明欧拉函数
证明错排问题