數學專題1

小笨笨qaq發表於2018-11-08

數學是好的——數學老師

在資訊學中,數學依然重要!!!

為腎膜?

蒟蒻:我都知道

看看歷年的曾題:

NOIP2017 D1T1 小凱的疑惑

不定方程大佬(nao)一算,

a*b-a-b

得解!!!

AK*1,MARK+=100;

 

NOIP2016 D2T1 組合數問題

組合數學的遞推+字首和=>AK*2,MARK+=100;

雖然我聽大佬說這題這麼解。

 

NOIP2014 D2T3最後一道

質數篩法+簡(du)單(liu)高精=>AK*3,MARK+=100;

 

還有很多:

計算係數,同餘方程,轉圈遊戲······

~~~~~~~~~~~~~~~~~~~~

幾乎每一屆NOIP都有數學。

~~~~~~~~~~~~~~~~~~~~

數學老師說:數學是好的。

先把他請出去,這是資訊教室。

 

而且,數學是比較好理解的演算法之一,他包含了:質數,質數篩法,最大公約數(gcd),最小公倍數(lcm),尤拉函式,歐幾里得演算法,中國剩餘定理,組合數學······

 

其實,你有一定的數學基礎時,大概一天就能把這些演算法摸一遍。

 

今天,我們先來講質數,質數篩法,互質以及尤拉函式。

~~~~~

  質數

~~~~~

只有1和它本身為因數的數叫質數。

特別地,1不是質數。

合數:除1和質數以外的正整數叫合數。

 

常識:100以內有25個質數。

 

——————

   質數判定

——————

在放程式碼之前,我們先舉幾個栗子。

 

15。

我們手判質數會這樣:(假設我們不知道它是不是)

15/2=7······1,

15/3=5

SO

15不是質數。

 

77.

手判質數:

77/2=38······1

77/3=25······2

······

77/7=11

SO

77也不是質數。

 

13.

13/2=6······1

13/3=4······1

13/4=3······1

ceil(sqrt(13))(根號13取上整)=4,

若13/2,3,4除不盡,13就是質數。

 

為什麼呢?

蒟蒻:13本來就是質數。

 

好。來證明一下:

若x是合數,設它的一個因數為a,則x/a必是它的因數。

所以,只要算sqrt(x)就可以了。

 

code:

 1 bool prime(int x)
 2 {
 3       if(x<=1)   return 0;
 4       if(x==2)   return 1;
 5       for(int i=2;i<=sqrt(x);i++)
 6       {
 7             if(x%i==0)
 8             return 0;
 9       }
10       return 1;
11 }

 

質數也有篩法,普通暴力篩我就不講了,就是一個一個判。

 

我們要講到的事線性篩,又叫尤拉篩法。

 

從 2 開始列舉當前數 i,去掉 i×p 這個合數,其中 p 是質數,且 p<i。 每個合數只會被其最小的質因子篩去,所以總的複雜度是線性的。

這就是它叫線性篩的原因。

我們先來看程式碼:

code:

 1 memset(check,0,sizeof(check));//標記
 2 int tot = 0;//質數個數
 3 for(int i=2;i<=n;i++)
 4 {
 5     if(!check[i])//i沒有別刪去,則他是質數 
 6     {
 7         prime[++tot]=i;
 8     }
 9     for(int j=1;j<=tot;j++)//去除i的倍數 
10     {
11         if(i*prime[j]>n)//超過n,退出 
12         {
13             break;
14         }
15         check[i*prime[j]]=1;//劃去合數 
16         if(i%prime[j]==0)
17         {
18             break;//合數被最小因子劃去 
19         }
20     }
21 } 

 

 

理解 i % prime[j] ==  0 是關鍵
原理:
1、任何一個合數都可以表示成一個質數和一個數的成績
2、假設A是一個合數,且A=x*y,這裡x也是一個合數,那麼有:
A=x*y(假設x是合數,y是質數)
x=a*b(假設a是質數,則a<x –> a<y)
A=a*b*y=a*Z (Z=b*y)  
3、即一個合數x與一個質數y的乘積能表示成一個更大的合數Z和一個更小的質數a乘積表示
所以對於當前i,若i % prime[j] == 0 –> i = prime[j] * x;
所以對於之後的任意數 i * prime[j+1] = prime[j] * prime[j+1] * x = prime[i] * y
即對於之後的數,我們都能用prime[j] * 一個更大的數來篩去,所以這裡不用重複篩了
由於每個數只可能被最小的素數篩掉,所以複雜度為O(n)。

 

~~~~~~~~~~~~~

      尤拉函式

~~~~~~~~~~~~~

尤拉函式就是表示小於n的數中與n互質的數的個數

 

code:

 1 int euler(int n){
 2     int ans = n;
 3     for(int i = 2; i * i <= n; i ++){
 4         if(n % i == 0){
 5             n /= i;
 6             ans   = ans / i * (i-1);
 7             while(n % i == 0){
 8                 n /= i;
 9             }
10         }
11     }
12     if(n > 1) ans = ans / n * (n - 1);
13     return ans;
14 }

計算方法
φ(n) = n*(1-1/p1)*(1-1/p2)…
其中pi表示的是n的各個質因子
直接列舉質因數計算

其實沒啥技術含量。

 

自己看一看就好利。畢竟蒟蒻都看懂了嘛

 

今天的內容就到這,希望大家在做資訊數學題時rp+++;


相關文章