【数论专题】

这篇博客深入探讨了数论中的递归问题,如汉诺塔和平面分割问题,并详细介绍了整除、素数、模运算、最大公约数等相关概念。此外,还重点讲解了莫比乌斯函数及其在莫比乌斯反演中的应用,最后给出了相关的习题和解决方案。

一、递归问题(引子)

1.hanoi双塔问题

①经典hanoi双塔

给你n个盘子,3根柱子分别标为ABC,n个盘子从上到下大小递增,要求大盘不能放在小盘上面且每次只能动一个盘子

问:将盘子全部转移到C柱需要多少步

要使最大的盘子到C柱,较小的n-1个盘子必须先到B柱,大盘再到C柱,小盘再到C柱,即:

Fn=2Fn1+1,F0=0 F n = 2 F n − 1 + 1 , F 0 = 0

我们考虑这个式子的封闭形式

Fn+1=2(Fn1+1) F n + 1 = 2 ( F n − 1 + 1 )

Gn=Fn+1 G n = F n + 1

Gn=2Gn1,G0=1 G n = 2 G n − 1 , G 0 = 1

Gn=2n G n = 2 n

即:

Fn=2n1 F n = 2 n − 1

这样我们就可以在 O(logn) O ( log ⁡ n ) 的复杂度内解决这个问题了


②复杂情况

如果每次转移不允许最大的盘子直接到目标柱呢

这样就需要把小盘子先移到目标柱,再将大盘过中继柱,小盘回原柱,大盘到目标柱,小盘到目标柱

可得: Fn=3Fn1+2 F n = 3 F n − 1 + 2

类比上式可得封闭形式:

Fn=3n1 F n = 3 n − 1


③扩展

m柱n盘hanoi塔问题求解

设有i个盘子,j个柱子时的答案为 f[i][j] f [ i ] [ j ] ,则有:

f[i][j]=min(2f[k][j]+f[ik][j1]) f [ i ] [ j ] = m i n ( 2 f [ k ] [ j ] + f [ i − k ] [ j − 1 ] )

即:将k个盘子拿走,剩余盘子拿到目标柱,再转移k个盘子,组合的最小值即为所求

#include<cstdio>
#include<algorithm>
using namespace std;

const int MAXN=2005,INF=0x7f;

int n,m;
int f[MAXN][MAXN];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=2;i<=m;++i) f[1][i]=1;
    for(int i=3;i<=m;++i) f[2][i]=3;
    for(int i=2;i<=n;++i) f[i][3]=f[i-1][3]*2+1;
    for(int j=4;j<=m;++j){
        for(int i=3;i<=n;++i){
            int minn=0x7fffffff;
            for(int k=1;k<i;++k){
                minn=min(minn,f[k][j]*2+f[i-k][j-1]);
            }f[i][j]=minn;
        }
    }printf("%d\n",f[n][m]);
    return 0;
}


2.平面分割问题

①直线分割平面

问:n条直线最多将平面分割为几部分

我们考虑交点对答案的影响

第i条直线最多与其他直线形成i-1个交点,每两个相邻交点之间的线段将原区域分为两份,另外两条射线各将原平面分为两份

则有: Fn=Fn1+n F n = F n − 1 + n

即:

Fn=i=1ni+1=n(n+1)2+1 F n = ∑ i = 1 n i + 1 = n ( n + 1 ) 2 + 1


②角分割平面

问:n个角最多能将平面分割为几部分

每个角可看作两条相交直线去掉交点一侧后剩下的部分

即去掉的一侧不再能够分割平面,共少分割了2n个

可得: Gn=F2n2n G n = F 2 n − 2 n

即:

Gn=2n(2n+1)2+12n=2n2n+1 G n = 2 n ( 2 n + 1 ) 2 + 1 − 2 n = 2 n 2 − n + 1




二、数论

1.整除

①定义

对于整数 n,m n , m ,若 m0 m ≠ 0 且存在整数k,使得 km=n k m = n ,我们就称m整除n,m是n的约数,n是m的倍数,记作 m|n m | n


②性质
  1. a|a a | a
  2. (a|b)(b|a)a=±b ( a | b ) ∧ ( b | a ) ⇒ a = ± b
  3. (a|b)(b|c)a|c ( a | b ) ∧ ( b | c ) ⇒ a | c
  4. (b0)(a|b)|a||b| ( b ≠ 0 ) ∧ ( a | b ) ⇒ | a | ≤ | b |
  5. a|bam|bm a | b ⇔ a m | b m
  6. (a|b)(a|c)a|(bx+cy) ( a | b ) ∧ ( a | c ) ⇔ a | ( b x + c y )


2.素数

①定义

一个大于1的整数,除了1与其自身外,不能被其他正整数整除的数叫作素数,否则叫作合数


②判定

方法1:枚举 2 n 2   n 的正整数,判定能否整除n,复杂度 O(n) O ( n )

方法2:枚举 2 n 2   n 的素因子,判定能否整除n,复杂度 O(nlogen) O ( n l o g e n )


③约数个数

对于整数

n=i=1pinprii n = ∏ i = 1 p i ≤ n p i r i

由乘法原理可得其约数个数为:

i=1pin(ri+1) ∏ i = 1 p i ≤ n ( r i + 1 )


④筛法求素数

埃氏筛 O(nlnlnn) O ( n ln ⁡ ln ⁡ n )

#include<cstdio>
#include<bitset>
using namespace std;

const int MAXN=1e6;

int n,p[MAXN];
bitset<MAXN*10> b;

int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;++i){
        if(!b[i]){
            p[++p[0]]=i;
            for(int j=i+i;j<=n;j+=i) b[j]=1;
        }
    }for(int i=1;i<=p[0];++i) printf("%d ",p[i]);
    return 0;
}

欧拉筛 O(n) O ( n )

#include<cstdio>
#include<bitset>
using namespace std;

const int MAXN=5e6+5;

int n;
int p[MAXN];
bitset<MAXN*10> b;

int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;++i){
        if(!b[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&p[j]*i<=n;++j){
            b[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }for(int i=1;i<=p[0];++i) printf("%d ",p[i]);
    return 0;
}

⑤应用

给定n (n<10000) ( n < 10000 ) 个int范围的数 ai a i ,判定其为素数or合数

读入 ai a i 时预处理 amax a m a x

欧拉筛筛出 [1,amax] [ 1 , a m a x ] 范围的质数

[2,ai] [ 2 , a i ] 范围的质数试除

复杂度 O(namaxlnamax) O ( n a m a x ln ⁡ a m a x )

#include<cstdio>
#include<bitset>
#include<cmath>
using namespace std;

const int MAXN=1e4+5;

int n;
int a[MAXN],p[MAXN];
bitset<MAXN*10> b;

inline int max(int a,int b){
  
  return a>b?a:b;}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]),a[0]=max(a[0],a[i]);
    a[0]=sqrt(a[0]);
    for(int i=2;i<=a[0];++i){
        if(!b[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&i*p[j]<=a[0];++j){
            b[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }for(int i=1;i<=n;++i){
        bool fl=1;
        for(int j=1;j<=p[0]&&p[j]*p[j]<=a[i];++j){
            if(a[i]%p[j]==0){fl=0;break;}
        }if(fl) puts("Yes");
        else puts("No");
    }return 0;
}

⑥区间筛

给定 L,R(1LR109,RL<105) L , R ( 1 ≤ L ≤ R ≤ 10 9 , R − L < 10 5 ) ,求 [L,R] [ L , R ] 范围的素数

线性筛 [1,R] [ 1 , R ] 范围素数,再对 [L,R]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值