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<iostream>
#include<string>
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;
}

B

水题,模拟就行

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

#include<iostream>
#include<string>
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;
}

C

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

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

#include<iostream>
#include<map>
#include<algorithm>
#include<string>
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;
}
 

D

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

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

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
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;
}

E

应该是最水的一个题了

#include<iostream>
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;
}

F

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

#include<iostream>
#include<string>
#include<unordered_map>
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;
}

G

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

#include<iostream>
#include<string>
#include<unordered_map>
#include<stack>
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;
}

H

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

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

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

I

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

#include<iostream>
#include<algorithm>
#include<queue>
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;
}

J

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

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

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

#include<iostream>
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值