Noip数学整理
Noip数学整理
序
- 因为某些原因, Noip对于数学方面的考纲仅停留在比较小的一部分,而这一部分在平常的做题中接触较少我做的题目太少, 为了防止NOIP爆炸, 整理一些Noip的数学知识还是有用的。
 
1 取模相关
n%p所得结果的正负由n决定,与p无关。如:7%4=3,-7%4=-3,-7%-4=-3---xun学姐- 欧拉定理 \(\alpha^{\phi(p)} \equiv 1 mod(p)\)
 - 当p为质数的特殊情况 $\alpha^{p - 1} \equiv 1 $
 - Noip2014式取模, 如果f(x) = 0, 那么f(x) % p = 0, 在式子中带入数字看脸计算。
 - 常数较小的取模方式
 
void upd(int &x, int y)
{
    x += y, x -= x >= mod ? mod : x;
}
2 质数相关
质数判定
- 根号判断比较稳
 
bool check(int x)
{
    for(int i = 2; i * i <= x; i++)
        if(x % i == 0)return false;
    return true;
}
- Miller robin比较骚\(-------\)chentongfei
 
bool check(int x)
{
    for(int i = 1; i <= 20; i++)
    {
        int op = read() % x + 1;
        while(op == x) op = rand() % x + 1;
        if(poww(op, x - 1, x) != 1) return false;
    }
    return true;
}
- 线性筛比较经典
 
void shai()
{
    isnt[1] = true;
    for(int i = 2; i <= n; i++)
    {
        if(!isnt[i]) sta[++tp] = i;
        for(int j = 1; j <= tp && i * sta[j] <= n; j++)
        {
            isnt[i * sta[j]] = true;
            if(i % sta[j] == 0) break;
        }
    }
}
- 区间筛比较没用
 
void shai(ll l, ll r)
{
    for(int i = 2; i * i <= r; i++)
    {
        if(!isnt[i])
        {
            for(int j = 2 * i; j * j<= r; j += i) isnt[j] = true;
            for(ll j = max(2ll, (l + i - 1) / i ) * i; j <= r; j += i) vis[j - l] = true;
        }
    }
    for(ll i = 0; i <= b - a; i++) if(!vis[i]) sta[++tp] = i + a;
}
质数应用
- 用来取模
 
3.基本操作
快速幂 or 慢速乘
- ???
 - O1快速乘吼啊
 
inline long long multi(long long x,long long y,long long mod) {
	long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
	return tmp<0 ? tmp+mod : tmp;
}
逆元
费马小定理
- 一定要检查一下模数是不是质数啊啊啊啊
 
exgcd求逆元
\(a * b \equiv 1\; mod\; m\Rightarrow a * b - m * y = 1\) 如果解出\(gcd(a, m) = 1\), 那么就存在逆元了
int inv(int a, int p)
{
    int x, y;
    int tmp = gcd(a, p, x, y);
    if(tmp != 1) return false;
    return (x + p) % p;
}
质因数分解
根号算法
- 枚举到根号大小就能找出所有质因子了
 
pollard-Robin
- 基于随机化, 鸽笼定理, floyd判环的算法
 - 写起来挺舒适的
 
bool robin_miller(ll n) { //判断是否素数
	if(n < 2)    return false;
	if(n == 2)  return true;
	if(!(n & 1))    return false;
	ll u = n - 1, t = 0;
	while(!(u & 1)) u >>= 1, t++;
	if(t >= 1 && (u & 1) == 1) {
		for(int i = 0; i < s; i++) {
			ll a = rand() % (n-1) + 1;
			if(witness(a, n, u, t)) return false;   //不是素数
		}
	}
	return true;    //是素数
}
ll gcd(ll a, ll b) {
	if(a == 0)  return 1;
	if(a < 0)    return gcd(-a, b);
	while(b) {
		ll t = a % b;
		a = b;
		b = t;
	}
	return a;
}
ll pollard_rho(ll x, ll c) {
	ll i = 1, x0 = rand() % x;
	ll y = x0;
	ll k = 2;
	for(;;) {
		i++;
		x0 = (multi_mod(x0, x0, x) + c) % x;
		ll d = gcd(y - x0, x);
		if(d != 1 && d != x) return d;
		if(y == x0) return x;
		if(i == k) {
			y = x0;
			k += k;
		}
	}
}
void find_fac(ll n) {
	if(n == 1)    return;
	if(robin_miller(n)) {
		prime_factor.push_back(n);
		return;
	}
	ll p = n;
	while(p >= n) p = pollard_rho(p, rand() % (n-1) + 1);
	find_fac(p);
	find_fac(n / p);
}
4.方程相关
不定方程
- 扩展欧几里得求同余方程 \(ax + by = \gcd(a, b)\)
 
int exgcd(int a, int b, int &x, int &y)
{
    if(!b)
    {
        x = 1, y = 0;
        return a;
    }
    int ans = exgcd(b, a % b, x, y), tmp = x;
    x = y, y = tmp - a / b * y;
    return ans;
}
- 得到的解只是一组 \(ax + by = g\), 让\(x += g / b, y -= g/a\)依旧成立
 - 所以通解可以表示成\(x = x_1 + \frac{b}{\gcd(a,b)}, y = y_1 + \frac{a}{gcd(a, b)}\)
 - 对于求解\(ax + by = c\)的同余方程, 首先判断c是否是\(\gcd(a, b)\)的倍数, 不是的话则无解
 - 然后求出\(ax + by = \gcd(a, b)\) 的一组解, 之后让xy都乘以 \(g / \gcd(a, b)\)即可
 
线性同余方程组
- 互质情况: 中国剩余定理
 - 求解
 
\]
\]
\]
\]
得到的通解可以表示成
\]
其中\(k \in Z\; M = \prod m_i\; M_i = \frac{M}{M_i}\; t_i = M_i^{-1}\; mod m_i\)
int cn(int n)
{
    int sum = 1, ans = 0, x, y;
    for(int i = 1; i <= n; i++) sum *= m[i];
    for(int i = 1; i <= n; i++)
    {
        int op = sum / m[i];
        int zz = exgcd(op, m[i], x, y);
        ans = (ans + g[i] * op * x) % sum;
    }
    return (sum + ans) % sum;
}
- 不互质情况, 扩展中国剩余定理
 - 感觉和中国剩余定理不是很相似, 主要是基于方程的合并
 - 首先考虑两个同余方程
 
x \equiv a_2\; mod\; m_2
\]
- 化成另一个形式
 
x = n_2 * m_2 + a_2
\]
- 联立可得
 
n_1 * m_1 - n_2 * m_2 = a_2 - a_1
\]
- 有解的前提是
 
\]
- 设
 
c = a_2 - a_1
\]
- 则
 
n_1 \frac{m_1}{d} \equiv \frac{c}{d} \ mod \ \frac{m_2}{d}
\]
- 移项
 
n_1 = \frac{c}{d} * inv(\frac{m_1}{d}, \frac{m_2}{d}) + y_1 * \frac{m_2}{d}
\]
然后\(n_1\)代入最上面的狮子可以得到
x = m_1 * \frac{c}{d} * inv(\frac{m_1}{d}, \frac{m_2}{d}) + y_1 * \frac{m_2 m_1}{d} + a_1\\
x \equiv m_1 * \frac{c}{d} * inv(\frac{m_1}{d}, \frac{m_2}{d}) + a_1 \ mod \ \frac{m_2 m_1}{d}
\]
- 然后就是个新方程了
 - 当然也适用于互质情况
 - 板子
 
int ex_crt()
{
    int a1 = a[1], m1 = m[1], a2, m2;
    for(int i = 2; i <= n; i++)
    {
        a2 = a[i], m2 = m[i];
        int c = a2 - a1;
        int d = gcd(m2, m1);
        if(c%d) return -1;
        ll k = inv(m1 / d, m2 / d);
        a1 = a1 * c / d * k + a1;
        m1 = m1 * m2 / d;
    }
    return a1;
}
裴蜀定理
- 对于方程 \(ax + by = c\) 有解当且仅当 \(\gcd(a,b) | c\) 可以扩展到多元, 经常被出题人用来出套路题
 
5.数列相关
卡特兰数
- 前几项!!!! \(1\ 1\ 2\ 5\ 14\ 42\ 132\)
 
递推式
C_n = C_{n - 1} * (4n - 2)/ (n + 1)
\]
组合式
h(n) = \frac{C_{2n}^{n}} { (n + 1)}
\]
意义
- 括号化问题。矩阵链乘: P=A1×A2×A3×……×An,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?
 - 将多边行划分为三角形问题。将一个凸多边形区域分成三角形区域(划分线不交叉)的方法数
 - 出栈次序问题。一个栈(无穷大)的进栈序列为1、2、3、...、n,有多少个不同的出栈序列?
 - 给顶节点组成二叉树的问题。
 
组合数
求法
杨辉三角
- 可更改性比较好, 适用于非质数取模
 
阶乘法
- 预处理On, 计算一次logn, 需要On的空间
 
卢卡斯定理
- 适用于模数较小且为质数
 
\]
扩展卢卡斯
- 适用于模数较小非质数或者模数较大但是分解后因子较小
 - 相当于我们对于模数分解后分别求出在mod某个数字下组合数是多少
 - 然后使用crt合并就好了
 - 当质因数分解不干净的时候, 我们要求\(Lucas(n, m, p^t)\)这个也是个问题
 - 这里利用循环节来统计阶乘中不含p因子的数字乘积, 对于含p因子的提出来递归计算
 - Noip考这个我直播吃拖鞋
 - 贴个板子
 
#include <bits/stdc++.h>
using namespace std;
int t,opt;
long long p[50],a[50];//存储质因数p的t次方,a存储CRT要用的余数
map<long long,long long> mp;
long long ji;
inline long long ksm(long long x,long long y,long long mod)
{
    long long res=1;
    while(y)
    {
        if(y&1)
        res=(res*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return res;
}
inline void exgcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x=1;
        y=0;
    }
    else
    {
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
inline long long inv(long long a,long long b)
{
    long long x=0,y=0;
    exgcd(a,b,x,y);
    x=(x%b+b)%b;
    if(!x)
    x+=b;
    return x;
}
inline long long cal(long long n,long long x,long long mod)//递归计算除了x的若干次方之外的部分(第一、第三部分)
{
    if(!n)
    return 1;
    long long ans=1;//提出来的那些不含因子x的乘积
    if(n/mod)//有整块的
    {
        for(int i=1;i<=mod;++i)
        {
            if(i%x)//不含因子x
            ans=ans*i%mod;
        }
        ans=ksm(ans,n/mod,mod);//有循环节,所以乘积用快速幂计算即可
    }
    for(int i=n/mod*mod+1;i<=n;++i)
    {
        if(i%x)
        ans=ans*i%mod;
    }
    return ans*cal(n/x,x,mod)%mod;//当前的不含因子x的乘积乘以递归下去求的剩余阶乘部分的结果
}
//计算出对于每一个质数的若干次方取模后的结果
inline long long exlucas(long long m,long long n,long long x,long long mod)//x是当前质数
{
    if(n>m)
    return 0;
    int cnt=0;
    for(int i=m;i;i/=x)
    cnt+=i/x;
    for(int i=n;i;i/=x)
    cnt-=i/x;
    for(int i=m-n;i;i/=x)
    cnt-=i/x;
    long long ans=ksm(x,cnt,mod)*cal(m,x,mod)%mod*inv(cal(n,x,mod),mod)%mod*inv(cal(m-n,x,mod),mod)%mod;
    return ans*(ji/mod)%ji*inv(ji/mod,mod)%ji;//CRT合并!
}
inline long long gcd(long long x,long long y)
{
    return y?gcd(y,x%y):x;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&opt);
        if(opt==1)
        {
            long long x,y,p;
            scanf("%lld%lld%lld",&x,&y,&p);
            printf("%lld\n",ksm(x,y,p));
        }
        else if(opt==2)
        {
            mp.clear();
            long long aa,b,p;
            int pd=0;
            scanf("%lld%lld%lld",&aa,&b,&p);
            if(b==1)
            {
                printf("0\n");
                pd=1;
            }
            if(pd==1)
            continue;
            long long d=gcd(aa,p),t=1,k=0;
            while(d!=1)
            {
                if(b%d)
                {
                    printf("Math Error\n");
                    pd=1;
                    break;
                }
                ++k;
                b/=d;
                p/=d;
                t=(t*(aa/d))%p;
                if(b==t)
                {
                    printf("%lld\n",k);
                    pd=1;
                    break;
                }
                d=gcd(aa,p);
            }
            if(pd==1)
            continue;
            long long m=ceil(sqrt(p)),ans;
            for(int j=0;j<=m;++j)
            {
                if(j==0)
                {
                    ans=b%p;
                    mp[ans]=j;
                    continue;
                }
                ans=(ans*aa)%p;
                mp[ans]=j;
            }
            long long x=ksm(aa,m,p);
            ans=t;
            for(int i=1;i<=m;++i)
            {
                ans=(ans*x)%p;
                if(mp[ans])
                {
                    x=i*m-mp[ans];
                    printf("%lld\n",x+k);
                    pd=1;
                    break;
                }
            }
            if(!pd)
            printf("Math Error\n");
        }
        else
        {
            long long x,y,mod;
            scanf("%lld%lld%lld",&x,&y,&mod);
            ji=mod;//mod就是CRT的那个因子乘积和!
            if(mod==1)
            {
                printf("0\n");
                continue;
            }
            memset(p,0,sizeof(p));
            memset(a,0,sizeof(a));
            int cnt=0;//记录质数个数
            for(int i=2;i*i<=mod;++i)
            {
                if(mod%i==0)
                {
                    p[++cnt]=1;
                    while(mod%i==0)
                    {
                        p[cnt]*=i;
                        mod/=i;//把当前因子除掉对看是否是后面数的倍数无影响
                    }
                    a[cnt]=exlucas(y,x,i,p[cnt]);
                }
            }
            if(mod>1)
            {
                p[++cnt]=mod;
                a[cnt]=exlucas(y,x,mod,mod);
            }
            long long res=0;
            for(int i=1;i<=cnt;++i)
            res=(res+a[i])%ji;
            printf("%lld\n",res);
        }
    }
    return 0;
}
常见模型和性质
奇偶性
- 当且仅当
n & m == m时 \(C_n^m\) 为奇数 
插板法
- n种元素,每种可选择任意次或者不选,共选m
 
\]
全错排公式
\]
情况1:插入第i个元素时,前i-1个已经错位排好,则选择其中任意一个与第i个互换一定满足要求,选择方法共i-1种,前i-1位错排f[i-1]种,记f[i-1]*(i-1)
情况2:插入第i个元素时,前i-1个中恰有一个元素a[j]使得a[j]=j,其他i-2个错位排好,则将i与j交换,j在i-2位中的插入共i-1种,前i-2位错排f[i-2]种,记f[i-2]*(i-1)
6.函数相关
- Noip函数???
 - 貌似只有一次函数合二次函数了吧QAQ
 
Noip数学整理的更多相关文章
- NOIP数学相关模板整理
		
$O(n)$递推求逆元 #include<cstdio> #include<cstring> #include<algorithm> using namespace ...
 - NOIP模板整理计划
		
先占个坑 [update]noip结束了,弃了 一.图论 1.单源最短路 洛谷P3371 (1)spfa 已加SLF优化 #include <iostream> #include < ...
 - noip考点整理(应该不是很完整……)
		
部分来自百度百科.其他的博客 一.必须会的 1.暴力: DFS.BFS.灌水法搜索.回溯搜索.记忆化搜索.启发式搜索.最优性剪枝.可行性剪枝 2.贪心 3.模拟 4.骗分 二.基础算法 1.图论:SP ...
 - NOIp 数学知识点总结
		
推荐阅读 NOIp 基础数论知识点总结: https://www.cnblogs.com/greyqz/p/number.html 排列组合 常用公式 排列:\[\displaystyle A_n^m ...
 - $\rm{NOIp}$板子整理
		
怎么说呢,整理这个的目的就是为了有个简约的\(list\),方便以后查阅,复习起来不至于太吃力. 并且--好像重温一遍所有,会更有一些新的认识.这也算是对我所学的一点整理了吧. 一.并查集的两种方式 ...
 - bzoj 3293 数学整理
		
和1045一模一样,找到这道题的时候还愣了下神,最后发现样例都是 一样的,直接粘了1045的代码,具体题解看 http://www.cnblogs.com/BLADEVIL/p/3468729.htm ...
 - bzoj1257 数学整理二分查询
		
2013-11-15 21:55 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1257 要求求sigma k mod i(i<=n) ...
 - 【模板】【学习笔记】noip数学
		
一.素数 欧拉筛 void prime(){ check[]=; ;i<=n;i++){ if(!check[i])prim[++cnt]=i;//这个if语句后面没有大括号!! ;j<= ...
 - noip数学
		
一.取模运算 (1)定义 给定一个正整数p和一个整数n 一定存在此等式 n=k*p+r;其中k,r是整数,r大于等于0小于p 称k是n除以p的商,r为n除以p的余数 说明:同余式 正整数a,b对p取模 ...
 
随机推荐
- gaea-basic-components 知识点
			
github:https://github.com/ascoders/gaea-basic-components
 - pip查看已安装包列表
			
输入命令: pip freeze 结果: certifi==2018.10.15chardet==3.0.4Django==2.1.2idna==2.7pytz==2018.5requests==2. ...
 - bzoj 4660 Crazy Rabbit——LIS解决“相交”限制的思想
			
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4660 想到一个点可以用它与圆的两个切点表示.并想到可以把切点极角排序,那么就变成环上的一些区 ...
 - 【转】解决ubuntu13.10下,无法双击运行脚本文件
			
解决ubuntu13.10下,无法双击运行脚本文件 转自:http://www.aichengxu.com/other/975350.htm 首先,必须先设定好脚本的运行方法,当然如果只是she ...
 - piwik获取访客头像,自定义显示访问者头像(URL)和描述(标题和替代)
			
访客头像 自定义显示访问者头像(URL)和描述(标题和替代) 链接地址:https://plugins.matomo.org/VisitorAvatar#description
 - 【java】浅谈swtich
			
在java中switch后的表达式的类型只能为以下几种:byte.short.char.int(在Java1.6中是这样),java1.7后支持了对string的判断 switch 的括号一定是表达式 ...
 - SDRAM单字写操作
			
SDRAM单字写操作 1.单字写操作时序 2.写verilog程序体会 在初始状态,先写好跳转条件.If()....else... 3.通过仿顺序操作来实现连续写操作 首先完成单字写操作,然后跳转到下 ...
 - Excel技巧--时尚的圆环比例图
			
如上图,制作方法如下: 1.创建圆环图:选择表格,点击“插入”-->点击 圆环图. 2.删除图中的标题和标记,将圆环内径缩至最小: 3.复制表格的数据,重复两次粘贴到图表中: 4.依次选择内两环 ...
 - 获取 TUniConnection.SpecificOptions默认值和下拉框列表值
			
TUniConnection的SpecificOptions参数决定了数据库连接配置参数,但可惜的是,SpecificOptions设计器界面,Devart公司只能让它在设计期配置! Specific ...
 - DS二叉树--二叉树之数组存储
			
二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示.,如下图所示 从上图可以看出,右边的是 ...