• HNUCM—第14届蓝桥杯CC++组选拔赛


    HNUCM—第14届蓝桥杯C/C++组选拔赛

    A

    暴力是不行的,别问我怎么知道的,OI赛制一来先暴力,WA了再说

    观察一下,其实这是一个动态规划,如果我们知道n位数回文数的个数,那么我们可以知道n+2位数回文串的个数,但是我们要注意如果我们设dp[n]为n位数为n位回文数的个数时,dp[n+2]!=9*dp[n],因为当n位数被围在中间时,边界上的两位数是可以为0的,所以我们的dp[n]代表边界可以包含0时dp[n]的个数,最后我们的方程就是dp[n+2]=10 * dp[n],那么我们的结果就是dp[n]-边界为0的情况,也就是dp[n]-dp[n-2]

    #include
    #include
    using namespace std;
    long long dp[100] = { 0,10,10 };
    int main()
    {
        string s;
        int n;
        cin >> n;
        for (int i = 3; i <= n; i++)
        {
            dp[i] = dp[i - 2] * 10;
        }
        if (n == 2)
            cout << 9 << endl;
        else
        cout << dp[n]-dp[n-2] << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    B

    水题,模拟就行

    但是如果不用string的话要注意处理一下回车的问题

    #include
    #include
    using namespace std;
    int main()
    {
        int n, m,a=0,b=0;
        char c;
        cin >> n >> m;
        string s;
        for (int i = 0; i < n; i++)
        {
            cin >> s;
            for (int i = 0; i < m; i++)
                if (s[i] == 'M')
                    a++;
                else
                    b++;
        }
        cout << a << " " << b << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    C

    最难的一个题了吧,第一眼看成了数学,但是想了想应该是搜索,这题和letcode的一些搜索题风格很像,判重比较麻烦,不要使用浮点直接判,使用to_string来判重,注意为了方便判重我们需要先给数组排序,然后第二个相同的元素不需要进入递归,一定程度达到达到剪枝和判重的效果

    接着就是和为1,我们可以将其分成分子,分母,每次选的数与当前选的分母求出最小公倍数组成新的分母,再求出分子,继续搜索具体细节自己写一遍就明白了。

    #include
    #include
    #include
    #include
    using namespace std;
    int a[110];
    int ans, n;
    map<string, bool>mp;
    int gcd(int x, int y) {
        return y == 0 ? x : gcd(y, x % y);
    }
    int lcm(int x, int y) {
        return x / gcd(x, y)*y;
    }
    void dfs(int fz, int fm, string s, int pos) {
     
        if (fz == fm && fz) {
            if (!mp[s])
                ans++;
            mp[s] = true;
            return;
        }
        if (pos > n)return;
        if (fz == 0)dfs(1, a[pos], s + to_string(a[pos]), pos + 1);
        else {
            int m = lcm(a[pos], fm);
            int z = (m / a[pos]) + (m / fm) * fz;
            int g = gcd(m, z);
            dfs(z / g, m / g, s + to_string(a[pos]), pos + 1);
        }
        dfs(fz, fm, s, pos + 1);
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        sort(a + 1, a + 1 + n);
        dfs(0, 0, "", 1);
        if (ans)
            printf("%d\n", ans);
        else
            printf("No solution!\n");
        return 0;
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    D

    人比较懒,能用map不用其他。

    记录最大次数,然后在map中寻找和最大次数相等的元素,因为map中的键值是按照从小到大排序的,所以用迭代器遍历时也是由小到大输出的

    #include
    #include
    #include
    #include
    using namespace std;
    const int maxn = 1e6 + 10;
    long long nums[maxn];
    int main()
    {
        long long n, x;
        int ans = 0;
        cin >> n;
        map<long long , int>mp;
        for (int i = 0; i < n; i++)
        {
            scanf("%lld", &x);
            int y=(++mp[x]);
            ans = max(ans, y);
        }
        for (auto it=mp.begin();it!=mp.end();it++)
        {
            if (it->second == ans)
                printf("%lld ", it->first);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    E

    应该是最水的一个题了

    #include
    using namespace std;
    int main()
    {
        int n;
        int a = 0, b = 0;
        cin >> n;
        int x;
        for (int i = 0; i < n; i++)
        {
            cin >> x;
            a += x >= 80;
            b += x <= 20;
        }
        cout << a << " " << b << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    F

    从前往后依次出现“ILOVEX”,出现一次完整的记录一次,原因自行领悟

    #include
    #include
    #include
    using namespace std;
    int main()
    {
        string s;
        string s1 = "ILOVEX";
        while (cin >> s)
        {
            int cnt = 0, ans = 0;
            for (char c : s)
            {
                if (c == s1[cnt])
                    cnt++;
                if (cnt == 6)
                    cnt = 0, ans++;
            }
            cout << ans << endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    G

    栈存储当前的牌堆,用map存储表示是否当前牌堆中是否存在和要加入的牌相等的,如果存在,一直出栈,直到遇到相等的牌,出栈时注意每个出去的牌需要标记为已经在牌堆不存在了

    #include
    #include
    #include
    #include
    using namespace std;
    int main()
    {
        unordered_map<int, bool>mp;
        stack<int>st;
        int n,x;
        int ans = 0, num = 0;
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            cin >> x;
            if (mp.find(x) == mp.end() || mp[x] == false)
                mp[x] = true, st.push(x);
            else
            {
                num++;
                while (st.top() != x)
                {
                    num++;
                    mp[st.top()] = false;
                    st.pop();
                }
                mp[x] = false;
                num++;
                st.pop();
                ans = max(num, ans);
                num = 0;
            }
        }
        cout << ans << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    H

    判断正方形方法:三个条件同时满足(1:四条边相等,2:边不为0,3:有一个直角)

    判断矩形的话就是:条件1变为有2条对边相等

    思路很清楚,建议自己写一遍,就不给代码了,当然判断矩形方法还有很多

    I

    当时脑袋一抽看到优先级就想成了拓扑排序,实际就是一个搜索,建立有向图,边的方向为年龄小的指向年龄大的,看k可以到达哪些点

    #include
    #include
    #include
    using namespace std;
    bool graph[110][110] = { false };
    bool vis[110] = { false };
    int ans = 0;
    int n, m, k, u, v;
    void dfs(int start)
    {
    	for (int i = 1; i <= n; i++)
    	{
    		if (graph[start][i] && !vis[i])
    		{
    			vis[i] = true;
    			ans++;
    			dfs(i);
    		}
    	}
    }
    int main()
    {
    	cin >> n >> m >> k;
    	for (int i = 0; i < m; i++)
    	{
    		cin >> u >> v;
    		graph[v][u] = true;
    	}
    	dfs(k);
    	cout << ans << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    J

    这题更是让我怀疑自己是不是有点毛病,二进制转换十进制写反了,末尾写成首位了,最后还是队友帮忙检查才知道

    数据范围很小,基本上每种求素数方法都可以过,但是i*i<=num还是有必要的,不然1e9应该也过不了

    这里使用了筛法预处理了一下1到1000内的素数

    #include
    using namespace std;
    bool prime[1001];
    void init()
    {
    	prime[0] = true;
    	prime[1] = true;
    	for (int i = 2; i*i <= 1000; i++)
    		if (!prime[i])
    			for (int j = i * i; j <=1000; j += i)
    				prime[j] = true;
    }
    bool check(int x)
    {
    	long long num = 0;
    	int a[11] = { 0 }, len = 0;
    	while (x)
    	{
    		a[len++] = x&1;
    		x >>= 1;
    	}
    	for (int i = len - 1; i >= 0; i--)
    		num = num * 10 + a[i];
    	for (int i = 2; i * i <= num; i++)
    		if (num % i == 0)
    			return false;
    	return true;
    }
    int main()
    {
    	int m, n;
    	cin >> m >> n;
    	init();
    	int ans = 0;
    	for (int i = m; i <= n; i++)
    		if (!prime[i] && check(i))
    			ans++;
    	cout << ans << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    SSM整合(二)
    Java 正则表达式分组匹配
    VIM编辑器的各种指令
    对DataFrame按指定的行、列索引输出数据:lookup()函数
    【六:(mock数据)spring boot+mybatis+yml】
    利用TexturePacker 进行pvr.ccz与png互转
    接入小程序国产操作系统装上双翼
    数据结构 第2章 线性表(一轮习题总结)
    华为云ECS随时获取资源,企业功成在云间
    “Python+”集成技术高光谱遥感数据处理与机器学习深度应用
  • 原文地址:https://blog.csdn.net/jdjhsj/article/details/128179561