初等數論


前言:

如何評價 OI 逐漸 MO 化。

我數學不是很好,最近學了這玩意,寫一篇總結。

$\text{Part I 素數篩} $

  • 埃式篩 Eraosthenes

    • 大概思路:從2開始,由小到大掃描每一個數 \(x\),把他的倍數標記為合數。當掃描到一個數時,若尚未被標記,那么就是質數。
    • 復雜度:\(O(n \log \log n)\) 接近線性。
    • 代碼:
      void make_prime()
      {
          memset(prime,true,sizeof(prime));
          prime[0]=prime[1]=false;//0,1都不是素數 
          int t=sqrt(n);//開根號 
          for(int i=2;i<=t;i++)
          {
              if(prime[i])
              {
                  for(int j=2*i;j<=n;j+=i)//加倍 
                  {
                      prime[j]=false;
                  }
              }
          }
          return;
      }  
  • 線性篩

    • 大致思路:從小到大積累質因子
    • 復雜度:\(O(n)\)
  void init() {
    phi[1] = 1;
    for (int i = 2; i < MAXN; ++i) {
      if (!vis[i]) {
        phi[i] = i - 1;
        pri[cnt++] = i;
      }
      for (int j = 0; j < cnt; ++j) {
        if (1ll * i * pri[j] >= MAXN) break;
        vis[i * pri[j]] = 1;
        if (i % pri[j]) {
          phi[i * pri[j]] = phi[i] * (pri[j] - 1);
        } else {
          // i % pri[j] == 0
          // 換言之,i 之前被 pri[j] 篩過了
          // 由於 pri 里面質數是從小到大的,所以 i 乘上其他的質數的結果一定會被
          // pri[j] 的倍數篩掉,就不需要在這里先篩一次,所以這里直接 break
          // 掉就好了
          phi[i * pri[j]] = phi[i] * pri[j];
          break;
        }
      }
    }
  }

$\text{Part II Prime Numbers and Phi} $

\(\phi(n)\) 表示 \(1~n\) 中與 \(n\) 互質的個數。同時也是歐拉函數。

然后有很多好玩的性質,由於我 \(\LaTeX\) 實在不大行就先不寫了。

代碼:

void euler(int n)
{
	for(int i=2;i<=n;i++) ph[i]=i;
	for(int i=2;i<=n;i++)
	{
		if(ph[i]==i)
		{
			for(int j=i;j<=n;j+=i)
			{
				ph[j]=ph[j]/i*(i-1);
			}
		}
	}
}

$\text{Part III 歐幾里得} $

  • \(\gcd\):歐幾里得算法,俗稱輾轉相除。
int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}
  • 擴展歐幾里得:對於任意整數 \(a,b\) ,存在一對整數 \(x,y\) ,滿足 \(ax+by=\gcd(a,b)\) 。不過說句閑話,這個應該裴蜀定理。解這個方程算法被稱之為“擴展歐幾里得”。
int exgcd(int a,int b,int &x,int &y)
{
	if(a==0)
	{
		x=0;y=1;
		return b;
	}
	int d=exgcd(b%a,a,y,x);
	x-=b/a*y;
	return d;
}

提一嘴逆元:若整數 \(b,m\) 互質,且 \(b|a\),則存在一個整數 \(x\),使得 \(\frac{a}{b}\)\(a\times x\)\(m\) 同余。則稱 \(x\)\(b\) 的模 \(m\) 乘法逆元。然后這玩意一般都是用來轉換除法的。

$\text{Part IIII 同余方程} $

對於像 ACwing203 這種題直接用歐幾里得算法求出一種特解,然后就最小值即可。

中國剩余定理:

直接放代碼:

/*long long gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}*/
#include<cstdio>
#define ll long long
//擴展歐幾里得算法 
void gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(b==0){
        d=a;
        x=1,y=0;
    }
    else{//else不能省略 
        gcd(b,a%b,d,y,x);
        y-=(a/b)*x;
    }
}
//中國剩余定理 
ll China(int n,ll *m,ll *a)
{
    ll M=1,d,y,x=0;
    for(int i=0;i<n;i++) M*=m[i];
    for(int i=0;i<n;i++){
        ll w=M/m[i];
        gcd(m[i],w,d,d,y);
        x=(x+y*w*a[i])%M;
    }
    return (x+M)%M;
}
ll m[15],a[15];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lld%lld",&m[i],&a[i]);
    printf("%lld",China(n,m,a));
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM