数论板子大总结
在这里,将有我迄今为止学过的所有数论。
1、素数筛——埃拉托斯特尼筛法
时间复杂度:O(nloglogn)
方法:用每个素数筛所有它的倍数
证明:略
for (int i=2;i<=N;i++) is[i]=1;
for (int i=2;i<=N;i++)
if (is[i])
for (int j=i*i;j<=2000;j+=i)
is[j]=0;
2、素数筛——欧拉筛法
时间复杂度:O(n)
方法&证明:埃拉托斯特尼对于每个合数筛了很多遍,而欧拉对于每个合数只被自己的最小质因数所筛去
memset(is,1,sizeof(is));
for (int i=2;i<=100000;i++)
{
if (is[i]) prime[++cnt]=i;
for (int j=1;j<=cnt && i*prime[j]<=100000;j++)
{
is[i*prime[j]]=0;
if (i%prime[j]==0) break;
}
}
3、欧拉函数
求[2,n)中与n互质的数的个数
//欧拉函数记做Φ(n)Φ(n)
性质:
Φ(n)=Φ(Pa11)Φ(Pa22)Φ(Pa33)…Φ(Pass)Φ(n)=Φ(Pa11)Φ(Pa22)Φ(Pa33)…Φ(Pass)
P为n的质因数,在n中a为其质因数的幂
定理:
(1)如果p是素数,那么Φ(p)=p−1Φ(p)=p−1 (逆定理成立)
(2)如果p是素数,那么Φ(pa)=pa−pa−1Φ(pa)=pa−pa−1
(3)设n和m互质,Φ(nm)=Φ(n)∗Φ(m)Φ(nm)=Φ(n)∗Φ(m)
(4)p为n的质因数,a为对应指数,Φ(n)=n(1−1/p1)(1−1/p2)(1−1/p3)…(1−1/ps)Φ(n)=n(1−1/p1)(1−1/p2)(1−1/p3)…(1−1/ps)
推论:当n为奇数时,Φ(2∗n)=Φ(n)Φ(2∗n)=Φ(n)
(5)设n>2,那么Φ(n)Φ(n)是偶数
(6)设n为正整数,∑d|nϕ(d)=n∑d|nϕ(d)=n
//求一个数的欧拉函数
ll phi(ll x)
{
ll ans=x,c=x;
for (int i=2;i<=c/i;i++)
{
if (c%i==0) ans=ans/i*(i-1);
while(c%i==0) c/=i;
}
if (c>1) ans=ans/c*(c-1);
return ans;
}
//求[1,n]的欧拉函数
void euler(ll n)
{
ll cnt=0;
memset(is,1,sizeof(is));
is[1]=0;
for (ll i=2;i<=n;i++)
{
if (is[i]) prime[++cnt]=i,phi[i]=i-1;
for (int j=1;j<=cnt && prime[j]*i<=n;j++)
{
is[prime[j]*i]=0;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
4、欧拉定理&费马小定理&乘法逆元
欧拉定理:对于任何两个互质的正整数a和m(m>1),有aΦ(m)≡1(modm)aΦ(m)≡1(modm)
费马小定理:当m是质数时,am−1≡1(modm)am−1≡1(modm)
5、欧几里得算法
//求a和b的最大公因数,记做gcd(a,b)
//(最小公倍数记做lcm(a,b),显然lcm(a,b)=a*b/gcd(a,b))
又名辗转相除法
原理:gcd(a,b)=gcd(b,a%b)
(详情请参见更相减损术)
6、扩展欧几里得算法
求解ax+by=gca(a,b)的x和y
显然这是一个不定方程,所以有多组解,而ex_gcd可以得出其中一组解,然后我们可以通过转换求出所有解
证明:
因为ax+by=1ax+by=1 →→ ax+by+ab−ab=1ax+by+ab−ab=1 →→ a(x+b)+b(y+a)=1a(x+b)+b(y+a)=1
所以在求出一个可行解x之后,不断的把x+-b仍是该方程的一个解,利用这个性质可以求类似最小解的问题
void ex_gcd(ll a,ll b,ll &x,ll &y)
{
if (!b)
{
x=1;
y=0;
return ;
}
ex_gcd(b,a%b,y,x);
y-=a/b*x;
}
7、中国剩余定理
emm…证明太繁琐,附上百度百科的网址把
qwq
int CRT(int a[],int m[],int n)
{
int M=1;
int ans=0;
for (int i=1;i<=n;i++)
M*=m[i];
for (int i=1;i<=n;i++)
{
int x,y;
int Mi=M/m[i];
exgcd(Mi,m[i],x,y);
ans=(ans+Mi*x*a[i])%M;
}
if (ans<0) ans+=M;
return ans;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
· 用 C# 插值字符串处理器写一个 sscanf