Skip to content

Latest commit

 

History

History
89 lines (75 loc) · 2.87 KB

6th.md

File metadata and controls

89 lines (75 loc) · 2.87 KB

C/C++ A组 真题解答

  1. 6届 6题 该题为dfs的典型例题
  • 可以使用13个循环遍历后得到结果,优点是不需要脑子,不容易出错,缺点是代码有点多,要仔细编写。
  • 也可以手写dfs,优点是代码量少,对循环的次数要求不高,缺点是需要脑子,针对一些边界条件要仔细。参考代码:
#include <iostream>

using namespace std;

// 将题转换成,一个连通图,每个节点都是一张牌的点数

int countCard = 0; // 累计有多少张牌
int countType = 0; // 累计有多少种牌型

// 形参是指的是 目前遍历的牌的点数
void dfs(int n)
{
    if(countCard > 13) // 累计的牌超过了界限,没有必要继续下去了
    {
        return ;
    }

    if(n == 14) //必须遍历完 13 种类型的牌,但是牌的数量可以是 0,必须遍历完,必须,必须
    {
        if(countCard == 13) // 集满13张牌
        {
            countType++;
        }
    }
    else
    {
        for(int i = 0; i < 5; ++i)
        {
            countCard += i;// 第n种牌 选择i张牌
            dfs(n+1);
            countCard -= i; //函数返回,则记了一次牌型,那么回溯一张牌
        }
    }
}


int main(int argc, char *argv[])
{

    dfs(1);
    cout<<countType<<endl;
    return 0;
}
  1. 线性筛法求素数 算法关键思想:每个合数必有一个最小素因子,用这个最小因子筛掉合数,注意的一点就是合数一定是通过最小质素因子来筛选的,如果用其他的的因子来筛选那么会出现 同一个合数 可能会有很多的因子,所以会对同一个合数进行多次筛选,为了避免这些没有必要的重复筛选,我们要求只能使用最小的素因子来筛选合数
void cp(long num)
{
    unordered_map<int,bool> flag;
    vector<int> re;

    // 默认所有数都是素数,然后剔除里面的合数
    for(int i = 0; i <= num; ++i)
    {
        flag[i] = true;
    }

    for(int i = 2; i <= num; ++i)
    {
        if(flag[i])
            re.push_back(i);//保存素数
        //剔除合数
        for(auto it = re.begin(); it != re.end() && *it * i <= num; it++)
        {
            flag[*it*i] = false;//找到合数,为了保证这里的质因子是最小的质因子,所有有下面的判断
            if(i % *it == 0)// 重点,这里是说,只要找到了 i 对应的最小的质因子, 就不用找了,
                // 因为 例如 当到4的时候 4*3 进行一次 判决的话,那么后面使用 6*2 会重复,
                // 里面的 4*3 的4可以分解为 2*2 而 2 已经处理过得到 3*2 = 6
                // 也就是说如果已经有 i 质因子,那么就可以跳出,因为,该质因子会通过其他的迭代方式来得到该数据
                break;
        }
    }

    for(auto it:re)
    {
        cout<<it<<endl;
    }
}