Math Summary 数论总结
一、素数
Miller-Rabin
首先介绍一下伪素数:若n是一个正整数,且存在正整数a满足$a^{n-1}\equiv1\;(mod\;n)$
(费马小定理,但n不一定为素数)
那么我们说n是基于a的伪素数
如果一个数是伪素数,它很大概率是素数
但一个数不是伪素数,它一定不是素数
那么对于要判断的数$n$,我们只需要多次选取$a$来判断是否是伪素数即可
然而是否伪素数通过了所有底数的测试就很大概率是素数了呢?
其实有一种叫$Carmichael$数的东西,十亿内有$600$多个,最小的如$561$,可以通过所有底数的测试。
那咋整?我们可以继续探测啊QwQ
二次探测定理:若$a^2~mod~p=1$,且$a!=1$,$a!=-1$则$p$必为合数。
设$p-1=2^ld$,可以先测$a^d$,然后平方$l$次。
当两倍两倍往上加的时候,判断是否合法,如果出现不合法就$return$。判定方法结合定理看代码吧QwQ……
至于伪素数的判定就两倍两倍加回原数之后在弄吧。
代码和$Pollard~Rho$的放一起吧QAQ
Pollard Rho
大数分解……
暂时还不是很懂就不瞎讲了……先坑着吧,不过我写的是第一篇博客里的第二种判环方法QAQ
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std; LL T,maxn,x;
LL prime[]={,,,,,,,,}; LL Mul(LL a,LL b,LL MOD)
{
LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD;
return tmp<?tmp+MOD:tmp;
} LL Qpow(LL a,LL b,LL MOD)
{
LL ans=;
while (b)
{
if (b&) ans=Mul(ans,a,MOD);
a=Mul(a,a,MOD); b>>=;
}
return ans;
} LL gcd(LL a,LL b) {return b==?a:gcd(b,a%b);} bool Miller_Rabin(LL n)
{
if (n==) return ;
if (n< || n%==) return ;
LL m=n-,l=;
while (m%==) ++l, m>>=;
for (int i=; i<; ++i)
{
LL p=prime[i],w=Qpow(p,m,n);
if (w== || w==n- || p==n) continue;
for (int j=; j<=l; ++j)
{
LL u=Mul(w,w,n);
if (u== && w!= && w!=n-) return ;
w=u;
}
if (w!=) return ;
}
return ;
} LL Pollard_Rho(LL n,LL c)
{
LL x=rand()%n,y=x,p=,k=;
for (LL i=; p==; ++i)
{
x=(Mul(x,x,n)+c)%n;
p=x>y?x-y:y-x;
p=gcd(p,n);
if (i==k) y=x,k+=k;
}
return p;
} void Solve(LL n)
{
if (n==) return;
if (Miller_Rabin(n)) {maxn=max(maxn,n); return;}
LL t=n;
while (t==n) t=Pollard_Rho(n,rand()%(n-)+);
Solve(t); Solve(n/t);
} int main()
{
scanf("%lld",&T);
while (T--)
{
scanf("%lld",&x);
maxn=;
Solve(x);
if (maxn==x) puts("Prime");
else printf("%lld\n",maxn);
}
}
Code
埃筛,欧拉筛
没什么好说的,讲解网上的很好,直接上code吧
埃筛
void work(int n)
{
for (int i=;i<=n;++i)
if (!vis[i])
{
prime[++cnt]=i;
for (int j=i*;j<=n;j+=i)
vis[j]=;
}
}
Code
欧拉筛
void work(int n)
{
for (int i=;i<=n;++i)
{
if (!vis[i])
prime[++cnt]=i;
for (int j=;j<=cnt&&prime[j]*i<=n;++j)
{
vis[prime[j]*i]=;
if (i%prime[j]==)
break;
}
}
}
Code
二、欧拉函数
欧拉函数$φ(n)$表示1~n中与n互质的个数(注意1和任何数互质)
线筛欧拉函数
void Euler(long long n)
{
phi[]=;
for (int i=;i<=n;++i)
if (!phi[i])
for (int j=i;j<=n;j+=i)
{
if (!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-);
}
}
Code
欧拉定理:$a^{φ(n)}\equiv1\;(mod\;n)$
三、中国剩余定理(CRT)
CRT
中国剩余定理,就是用来求解一组同余方程组的一个解的,其中模数$m_{i}$两两互质
引入一个经典问题
“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题” (一个很妙的证明)
设$q_{1}$为$3*k+2$,也就是除3余2的一个数
同理设$q_{2}$为$5*k+3$,$q_{3}$为$7*k+2$
那么可以导出以下三点:
1、要使$q_{1}+q_{2}+q_{3}$的和满足除3余2,$q_{2}和q_{3}$必须是3的倍数
2、要使$q_{1}+q_{2}+q_{3}$的和满足除5余3,$q_{1}和q_{3}$必须是5的倍数
3、要使$q_{1}+q_{2}+q_{3}$的和满足除7余2,$q_{1}和q_{2}$必须是7的倍数
整理可得
1、$q_{1}$除以3余2,且是5和7的公倍数。
2、$q_{2}$除以5余3,且是3和7的公倍数。
3、$q_{3}$除以7余2,且是3和5的公倍数。
显然$q_{1}+q_{2}+q_{3}$是符合条件的一组解,可以用exgcd进行求解了
这里有一个小技巧,比如求$q_{1}$的时候可以求出除3余1的数然后再乘2,
也就是先求出5和7的公倍数模3下的逆元,再用逆元去乘余数。
看代码可能更好懂一点
long long CRT()
{
long long x,y,ans=,lcm=;
for(i=; i<=n; ++i) lcm=lcm*m[i];//因为互质
for(i=; i<=n; i++)
{
long long kl=lcm/m[i];
exgcd(kl,m[i],x,y);
x=(x%m[i]+m[i])%m[i];
ans=(ans+a[i]*x*kl)%lcm;
}
return ans;
}
Code
exCRT
用来解决模数不两两互质的同余方程组
假设我们这里有两个方程
$x = a_1 * x_1 + b_1$
$x = a_2 * x_2 + b_2$
$a_1,a_2$是模数,$b_1,b_2$是余数,那么我们可以合并这两个方程:
因为正负号对变量$x_1 , x_2$无影响,所以稍加变形可得:$a_1 * x_1 + a_2 * x_2 = b_2 - b_1$
然后扩欧就可以求解出最小正整数解$x_1$,那么令$k=(a_1*x_1+b_1)$
因为$k=a_1*x_1+b_1=a_2*x_2+b_2$,显然 $k$ 和$a_1 , a_2$分别同余 ,那么$ k $ 和 $ lcm( a_1 , a_2 ) $一定同余
所以 $x \equiv k \; (mod \; lcm( a_1 , a_2 ) )$
不停的合并就可以得到最终答案了
long long exCRT()//M是模数,A是余数
{
long long M=m[],A=a[],d,x,y;
for (int i=; i<=n; ++i)
{
exgcd(M,m[i],d,x,y);
if ((a[i]-A)%d) return -;
x*=(a[i]-A)/d; t=m[i]/d; x=(x%t+t)%t;
A=M*x+A; M=M/d*m[i]; A%=M;
}
A=(A%M+M)%M;
return A;
}
Code
四、Lucas
Lucas
证明不会,会用就行
Lucas用于解决当模数p为质数且比较小的时候,可以用$log$的复杂度解决求解$C(n,m)$
$Lucas(n,m) = Lucas(n/p,m/p)*C(n\%p,m\%p)$
其中$C(n\%p,m\%p)$可以通过预处理阶乘和阶乘的逆元$O(1)$进行求解
void Init(long long p)
{
fac[]=; inv[]=; facInv[]=;
for (int i=; i<=p; ++i)
{
if (i!=) inv[i]=(p-p/i)*inv[p%i]%p;
fac[i]=fac[i-]*i%p; facInv[i]=facInv[i-]*inv[i]%p;
}
} long long C(long long n,long long m)
{
if (m>n) return ;
return fac[n]*facInv[m]%MOD*facInv[n-m]%MOD;
} long long Lucas(long long n,long long m)
{
if (m>n) return ;
long long ans=;
for (; m; n/=MOD,m/=MOD)
ans=(ans*C(n%MOD,m%MOD))%MOD;
return ans;
}
Code
exLucas
可以解决$C(n,m)\%p$中模数不是质数的Lucas问题
首先我们将模数$p$分解,$p={p_1}^{k_1}*{p_2}^{k_2}*...*{p_q}^{k_q}$
很容易得出一组同余方程组
$\left\{ \begin{array}{c} ans\equiv c_1\pmod {{p_1}^{k_1}}\\ ans\equiv c_2\pmod {{p_2}^{k_2}}\\ ...\\ ans\equiv c_q\pmod {{p_q}^{k_q}}\\ \end{array} \right.$
很显然模数是两两互质的,只要求出每一个$c_i$那么我们就可以用中国剩余定理求解出$C(n,m)$了。
那么问题来了,怎么求解每一个$c_i$呢?
因为$C_n^m={n!\over m!(n-m)!}$,所以只要能求出 $n!~\% {p_i}^{k_i},~m!~\% {p_i}^{k_i},~(n-m)!~\% {p_i}^{k_i}$,我们就可以根据逆元求解每一个$c_i$了。
举个栗子
$n=22,p_i=3,k_i=2$
$22!=(1*2*3*4*5*6*7*8*9)*(10*11*12*13*14*15*16*17*18)*(19*20*21*22)$
剔除因子3之后
$22!=(1*2*4*5*7*8)*(10*11*13*14*16*17)*(19*20*22)*3^6*(1*2*3*4*5*6*7)$
发现按照如下分组后$3^6$前面部分的前$\frac{n}{{p_i}^{k_i}}$组在$mod~{p_i}^{k_i}$ 后结果相同,因此只需要算出来一组然后快速幂就好了。
对于冗余部分$(19*20*22)$暴力计算。
最后的$(1*2*3*4*5*6*7)$递归计算即可
3因子被剔除了就不考虑了
代码还写不来先坑着
未完待续目前懒得写了
Math Summary 数论总结的更多相关文章
- BZOJ3560 DZY Loves Math V 数论 快速幂
原文链接http://www.cnblogs.com/zhouzhendong/p/8111725.html UPD(2018-03-26):蒟蒻回来重新学数论了.更新了题解和代码.之前的怼到后面去了 ...
- BZOJ3561 DZY Loves Math VI 数论 快速幂 莫比乌斯反演
原文链接http://www.cnblogs.com/zhouzhendong/p/8116330.html UPD(2018-03-26):回来重新学数论啦.之前的博客版面放在更新之后的后面. 题目 ...
- Codeforces Round #270 A. Design Tutorial: Learn from Math【数论/埃氏筛法】
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...
- HDU 5974 A Simple Math Problem(数论+结论)
Problem Description Given two positive integers a and b,find suitable X and Y to meet the conditions ...
- [数论] hdu 5974 A Simple Math Problem (数论gcd)
传送门 •题意 一直整数$a,b$,有 $\left\{\begin{matrix}x+y=a\\ LCM(x*y)=b \end{matrix}\right.$ 求$x,y$ •思路 解题重点:若$ ...
- 【转】C# 将字符串或表达式直接转为可执行代码的办法
C# 将字符串或表达式直接转为可执行代码的办法 反射类 using System; using System.Data; using System.Configuration; using Syste ...
- WCF学习笔记 -- 如何用C#开发一个WebService
假设所有工程的命名空间是demo. 新建一个C#的ClassLibrary(类库)工程. 在工程引用中加入System.ServiceModel引用. 定义接口,你可以删除自动生成的代码,或者直接修改 ...
- 【Unity优化】构建一个拒绝GC的List
版权声明:本文为博主原创文章,欢迎转载.请保留博主链接:http://blog.csdn.net/andrewfan 上篇文章<[Unity优化]Unity中究竟能不能使用foreach?> ...
- 线性代数之行列式的C#研究实现
最近学习机器学习 才发现以前数学没有学好 开始从线性代数开始学起 读完行列式一章写了些C#的代码学习一下. 直接上C#代码: using System; using System.Collection ...
随机推荐
- webpack 报错 No PostCSS Config found 解决方案。
webpack 报错 No PostCSS Config found 这个问题我在百度上找了好久,也没有找到解决方案,最后没有办法只能自己去啃官方文档,本案例在本人的webpack 学习感悟中已经写 ...
- 搭建Web部署环境
这里使用Web轻量级的服务器Tomcat Tomcat常用作servlet的运行容器,在JavaWeb开发中广泛使用,当然,Tomcat也可为提供HTML页面服务. 主要步骤: Tomcat下载安装 ...
- SQL Server 获取(本周、本月、本旬、本季、本年)的某一天
/*------------------------------本周----------------------------------------*/ --本周第一天 ),getdate()) -- ...
- [C语言] 数据结构-预备知识指针
所有的伟大源于一个勇敢的开始 数据结构预备知识 指针 1.指针:是C语言的灵魂,指针=地址 地址:内存单元的编号 指针变量:存放内存单元地址的变量 int *p;//p是指针变量,int *表示该p变 ...
- 查看SQLServer数据库表占用大小
查看数据库mdf 文件中 各个表数据占用大小. create table #t(name varchar(255), rows bigint, reserved varchar(20), ...
- 撩课-Mysql详解第3部分sql分类
学习地址:[撩课-JavaWeb系列1之基础语法-前端基础][撩课-JavaWeb系列2之XML][撩课-JavaWeb系列3之MySQL][撩课-JavaWeb系列4之JDBC][撩课-JavaWe ...
- msql查询指定日期
今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...
- swoole框架快速入门
swoole有两个部分. 一个是PHP扩展,用C开发的,这是核心. 另一个是框架,像yii.TP.Laravel一样,是PHP代码写的. swoole扩展本身提供了web服务器功能,可以替代php-f ...
- Gradle修改缓存路径 和 Gradle修改Maven仓库地址
Gradle修改缓存路径 修改gradle启动脚本进入gradle安装的bin目录,使用文本编辑器打开gradle.bat文件,在如图的位置添加以下语句 set GRADLE_OPTS="- ...
- 关于JAVA项目报表选型过程
本人一直在走.NET技术路线,考虑到后期公司搞JAVA项目,也算是进行技术灾备,开始对JAVA技术进行关注.万事开头难,也是上来一头包.没办法,顶着上吧.上面开始分给我任务了.就是对后期项目报表进行方 ...