zoukankan      html  css  js  c++  java
  • CSP考纲及高精度计算

    转载请注明出处,部分内容引自

    SBSOI大佬

     

    转载请注明出处,部分内容引自

     大佬

    首先来一张图,很直观(截止到2012年数据)

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

    加粗表示特别重要,必须掌握
    其他表示最好掌握,可能性不是很大,但是某些可以提高程序效率

    高精度
      a.加法
      b.减法
      c.乘法(应该只会有高精乘单精)                               
      d.高精度除单精                 (后面c,d考的可能性较小,应该只考a,b)


    排序算法
      a.选择排序
      b.插入排序
      c.hash排序
      d.归并排序(单纯的排序可能用不到,有快排就行了,但是归并排序的思想很重要)
      e.堆排序
      f.快排

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

    数论
      a.欧几里德算法(用辗转相除法求最大公约数)
      b.扩展欧几里德算法 ax+by=c 的正整数
      c.素数  O(sqrt(n)) 
      d.筛法求素数
      e.快速乘方(位运算+同余+高精)

    树论
      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
      ......

     高精度算法

    1、高精度加法(简单版,以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;
    }
     

    2、高精度减法(简单版,以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;
    }

    3、高精度乘法(有两种:高精度*低精度,高精度*高精度)

    (以下代码只展示高精度*低精度,以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;
    }
     

    4、高精度除法(有两种:高精度/低精度,高精度/高精度)

    (以下代码只展示高精度/低精度,以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;
    }
     
  • 相关阅读:
    关于字符的C++函数
    VC6 LINK : fatal error LNK1168: cannot open Debug/Test.exe for writing
    1019 数字黑洞 (20)
    1015 德才论 (25)
    1013 数素数 (20)(20 分)
    1003 我要通过!(20)(20 分)
    今日目标
    MySQL单列索引和组合索引的区别
    Struts2中过滤器和拦截器的区别
    SQL 统计 字段 竖向转横向 (行转列)显示
  • 原文地址:https://www.cnblogs.com/CXYscxy/p/11599685.html
Copyright © 2011-2022 走看看