(Day6)演算法復健運動for藍橋杯-常用數學

wlqtc發表於2024-06-25

(Day6)演算法復健運動for藍橋杯-常用數學

1. 歐幾里得演算法:輾轉相除法(求gcd)

int gcd(int a, int b)
{
    return 0 == b ? a : gcd(b, a % b);
}

或者C++直接呼叫:

編譯沒過,說是不能是無符號數

unsigned int a=10,b=5;
cout<<__gcd(a,b);

2. 尤拉篩(求質數)

  int cnt=0;
  vis[0]=1;
  vis[1]=1;
  for(int i=2; i<=10000000; i++)
  {
      if(!vis[i])
      {
          prime[cnt++]=i;
      }
      for(int j=0;j<cnt&&(ll)i*(ll)prime[j]<=10000000;j++)
      {
          vis[i*prime[j]]=1;
          if(i%prime[j]==0)break;
      }
  }

3. 大數快速冪

ll f(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
        ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}

4. 矩陣快速冪

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MOD=10000;

struct mat
{
    ll a[2][2];
};

mat mat_mul(mat x,mat y)//兩個矩陣相乘
{
    mat res;//新的矩陣
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<2; i++)
        for(int j=0; j<2; j++)
            for(int k=0; k<2; k++)
                res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;
    return res;
}
void mat_pow(int n)
{
    mat c,res;
    c.a[0][0]=c.a[0][1]=c.a[1][0]=1;
    c.a[1][1]=0;
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<2; i++) res.a[i][i]=1;//初始為E
    while(n)//非常眼熟
    {
        if(n&1) res=mat_mul(res,c);
        c=mat_mul(c,c);
        n>>=1;
    }
    printf("%d\n",res.a[0][1]);
}

int main()
{
    int n;
    while(~scanf("%d",&n)&&n!=-1)
    {
        mat_pow(n);
    }
    return 0;
}

5. 逆元

a ∗ b ≡ 1 (mod p),那麼 a,b 互為模 p 意義下的逆元

費馬小定理:

∀a,n滿足gcd(a,n)==1,則a^φ(n)≡1(mod n)

當p是質數,且a不能被p整除時,有a^(p-1)≡1(mod p)

在計算模逆元素時,通常使用費馬小定理的一個特例,即對於素數p和整數a,如果a 不是 p 的倍數,則$a^{p-1} \equiv 1 \pmod{p} $。由於模逆元素的定義是乘以一個數得到1,因此我們可以將$a^{p-1}$視為a 的逆元素。

因此,當p是一個素數,且a不是p 的倍數時,我們有$ a^{p-1} \equiv 1 \pmod{p} $,這意味著a的逆元素是$a^{p-2}$。因此,我們可以使用$ a^{p-2} $來計算a的模逆元素。

這種方法在很多情況下是有效的,因為它只需要進行一次指數運算和一次模運算,相對於其他求逆元素的方法更為高效。

所以廢話少說,求逆元就是,a%mod*f(b,mod-2)%mod

6. 唯一分解定理

任何一1的自然數N,如果N不為質數,都可以唯一分解成有限個質數的乘積
$N=p^a_1p_2 ^a ...p_n^a$
那麼,我們由中學所學的知識所知N的正因子共有(1+a1)
(1+a2)...(1+an)個

而這些因子(不只是質因數)的和為
$(1+p_1+p_12..p_1a)(1+p_2+p_22..p_2a)$...

7.補充

把字串格式的數字轉化為int數字的函式

char s[10];
int sum=atoi(s);

memcpy:可以複製陣列

int a[109];
int b[109];
memcpy(b,a,sizeof(a));

相關文章