CSP考綱及高精度計算

轉載請註明出處,部份內容引自html

SBSOI大佬

 

轉載請註明出處,部份內容引自
算法

 大佬數組

首先來一張圖,很直觀(截止到2012年數據)數據結構

 

下面是收集的一些,我改了一下函數

加粗表示特別重要,必須掌握
其餘表示最好掌握,可能性不是很大,可是某些能夠提升程序效率

學習

高精度
  a.加法
  b.減法
  c.乘法(應該只會有高精乘單精)                               
  d.高精度除單精                 (後面c,d考的可能性較小,應該只考a,b)優化


排序算法
  a.選擇排序
  b.插入排序
  c.hash排序
  d.歸併排序(單純的排序可能用不到,有快排就好了,可是歸併排序的思想很重要)
  e.堆排序
  f.快排spa

字符串匹配算法
  a.蠻力法
  b.KMP.net

數論
  a.歐幾里德算法(用展轉相除法求最大公約數)
  b.擴展歐幾里德算法 ax+by=c 的正整數
  c.素數  O(sqrt(n)) 
  d.篩法求素數
  e.快速乘方(位運算+同餘+高精)code

樹論
  a.二叉搜索樹
  b.優先隊列(C++中priority_queue,至關於手動維護的小(大)根堆的數據結構優化)
  c.線段樹 (RMQ問題建議使用st算法)
  d.平衡樹一種(建議學習SBT)

圖論
  a.拓撲排序
  b.割頂,割邊(橋) {O(n)}
  c.強連通分支  O(n)
  d.有向無迴路圖的最長路徑
  e.歐拉回路
  f.最小生成樹
    ① Prime  O(N2)
    ② Kruskal  O(M2
  g.次小生成樹 {簡單的刪除最大邊是不對的}
  h.最短路徑
    ① Dijkstra
    ② Bellman-ford
    ③ spfa
    ④ flyod
    單源點最短路徑算法推薦使用spfa(即便你習慣dijkstra),Dijkstra不能有負邊不能有迴路,因此用spfa更保險

計算幾何 
  a.判斷兩條線段是否相交
  b.凸包算法  O(n)

其餘算法
  a.並查集
  b.RMQ
  ......

 

 

 

 高精度算法

一、高精度加法(簡單版,以noi1.6:10大整數加法題爲例)

//noi1.6:10大整數加法
//題解:高精度入門題:結構體+字符轉換+進位 
#include<cstdio>
#include<cstring>
struct nod{int n,a[210];nod(){memset(a,0,sizeof(a));}}a,b;
char s[210];
int main()
{
    int ns;//讀入a============ 
    scanf("%s",s+1);//下標從1開始 
    ns=strlen(s+1);    a.n=ns;
    for(int i=1;i<=ns;i++)//字符逆序轉換爲數字 
    {//爲了數位 對齊,翻轉數字 
        a.a[ns-i+1]=s[i]-'0';
    }//========================
    
    //讀入b==================== 
    scanf("%s",s+1);//下標從1開始 
    ns=strlen(s+1);    b.n=ns;
    for(int i=1;i<=ns;i++)//字符逆序轉換爲數字 
    {//爲了數位 對齊,翻轉數字 
        b.a[ns-i+1]=s[i]-'0';
    }//=========================
    //模擬加法運算 
    a.n=a.n>b.n?a.n:b.n;//肯定數位 
    for(int i=1;i<=a.n;i++)//暴力加 
    {
        a.a[i]+=b.a[i];
    }
    for(int i=1;i<=a.n;i++)//處理進位 
    {
        if(a.a[i]>9)
        {
            a.a[i+1]+=a.a[i]/10;//向右進位 
            a.a[i]%=10;//保留個位數
            if(i==a.n) a.n++;//最高位溢出 
        }
    }
    //消除前導0
    while(a.a[a.n]==0&&a.n>1) a.n--;//最高位必須非0
    //反向輸出
    for(int i=a.n;i>=1;i--)
    {
        printf("%d ",a.a[i]);
    } 
    return 0;
}
 

 

二、高精度減法(簡單版,以noi1.6:11大整數減法題爲例)

//noi1.6:11大整數減法
//題解:高精度入門題:結構體+字符轉換+借位 
#include<cstdio>
#include<cstring>
struct nod{int n,a[210];nod(){memset(a,0,sizeof(a));}}a,b;
char s[210];
int main()
{
    int ns;//讀入a============ 
    scanf("%s",s+1);//下標從1開始 
    ns=strlen(s+1);    a.n=ns;
    for(int i=1;i<=ns;i++)//字符逆序轉換爲數字 
    {//爲了數位 對齊,翻轉數字 
        a.a[ns-i+1]=s[i]-'0';
    }//========================
    //讀入b==================== 
    scanf("%s",s+1);//下標從1開始 
    ns=strlen(s+1);    b.n=ns;
    for(int i=1;i<=ns;i++)//字符逆序轉換爲數字 
    {//爲了數位 對齊,翻轉數字 
        b.a[ns-i+1]=s[i]-'0';
    }//=========================
    //模擬減法運算  
    for(int i=1;i<=a.n;i++) a.a[i]-=b.a[i];//暴力減 
    for(int i=1;i<=a.n;i++)//處理借位 
    {
        if(a.a[i]<0)
        {
            a.a[i+1]-=1;//向右借 1 
            a.a[i]+=10;//補充數值 
        }
    }
    //消除前導0//本題保證a>b,若是不知道大小關係呢? 
    while(a.a[a.n]==0&&a.n>1) a.n--;//最高位必須非0
    //反向輸出
    for(int i=a.n;i>=1;i--) printf("%d",a.a[i]);
    return 0;
}

 

三、高精度乘法(有兩種:高精度*低精度,高精度*高精度)

(如下代碼只展現高精度*低精度,以noi1.6:12:計算2的N次方 題爲例)

//noi1.6:12計算2的N次方 
//題解:高精度*低精度 +非結構體 +函數 
#include<cstdio>
int a[1010],na;//估算數組,2的100次不知道是多少位?
//10的100次是1000位,能夠了嗎?
void cf(int x)
{
    for(int i=1;i<=na;i++)//每位都乘 
    {
        a[i]*=x;
    }
    for(int i=1;i<=na;i++)//處理進位 
    {
        if(a[i]>9)
        {
            a[i+1]+=a[i]/10;
            a[i]%=10;
            if(i==na) na++;//最高位溢出 
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    a[1]=1;na=1;
    for(int i=1;i<=n;i++)
    {
        cf(2);
    }
    for(int i=na;i>=1;i--) printf("%d",a[i]);//反向輸出 
    
    //如今你能夠知道2的100次方是多少位了嗎? 
    
    return 0;
}
 

 

四、高精度除法(有兩種:高精度/低精度,高精度/高精度)

(如下代碼只展現高精度/低精度,以noi1.6:13:大整數的因子 題爲例)

//noi1.6:13大整數的因子 
//題解:高精度除以低精度:模擬思想 
#include<cstdio>
#include<cstring>
char s[210];
int a[210],na,ls=0; 
void chu(int x)
{
    int k=0;//餘數 
    for(int i=na;i>=1;i--)//模擬豎式除法 
    {
        k=k*10+a[i];
        k=k%x;
    }
    if(k==0) 
    {    ls=1; //打標籤 
        printf("%d ",x);
    } 
}
int main()
{
    int ns;
    scanf("%s",s+1);//下標從1開始 
    ns=strlen(s+1);    na=ns;
    for(int i=1;i<=ns;i++)//字符逆序轉換爲數字 
    {
        a[ns-i+1]=s[i]-'0';
    }
    for(int i=2;i<=9;i++)
    {
        chu(i);//函數處理 
    }
    if(ls==0) printf("none"); 
    return 0;
}
 
相關文章
相關標籤/搜索