选拔赛补题

本文汇总了CodeForces上多个编程竞赛题目,分析了解题思路和常见算法应用,包括动态规划、最短路径、区间问题、数学推理等。通过实例解析,展示了在面对不同类型题目时如何找到解决方案,提升编程竞赛能力。
摘要由CSDN通过智能技术生成

CodeForces 550C Divisibility by Eight

这题打的时候时候打了个表,除了0、8,就没找出规律了,当时直觉是一定能通过有限的组合,在0-9之间组合出8的倍数,卡在找数的规律和如何组合数了
规律结论
只需要暴力判1-3位就行
官方题解给的是dp:https://codeforces.com/blog/entry/18329

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
		string s;
		cin >> s;
		int len = s.size();
		for (int i = 0; i < len; ++i){
			if((s[i] - '0') % 8 == 0){
				cout << "YES"<<endl<<s[i];
				return 0;
			}
			for (int j = i + 1; j < len; ++j){
				int temp = (s[i] - '0') * 10 + (s[j] - '0');
				if(temp % 8 == 0){
					//cout << temp << " ";
					cout << "YES"<<endl<<s[i]<<s[j];
					return 0;
				}
				int t = temp;
				for (int k = j + 1; k < len; ++k){
					temp = t;
					//cout << temp << " ";
					temp = temp * 10 + (s[k] - '0');
					if(temp % 8 == 0){
						cout << "YES"<<endl<<s[i]<<s[j]<<s[k];
						return 0;
					}
				}
			}
			//cout << endl;
		}
	cout << "NO";
	return 0;
}

CodeForces 7C Line

板子题,板子不对,sad

#define ll long long

ll exgcd(ll a, ll b, ll &x, ll &y){
    if(!b){
        x = 1, y = 0;
        return a;
    }
    ll d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

int main(){
    ll a, b, c, x, y;
    cin >> a >> b >> c;
    ll d = exgcd(a, b, x, y);
    if(c % d) {
        cout << -1 << endl;
        return 0;
    }
    x *= -c / d;
	y *= -c / d;
	cout << x << " " << y;
    return 0;
}

CodeForces 977F Consecutive Subsequence

map原来还可以这么用,大震惊
因为连续上升,所以直接用map存取数量最大的值,选取最终的数量最大的值进行倒推

#define ll long long
const int maxn = 2e5 + 5;
map<ll,ll> mp;
ll a[maxn];

int main(){
	ll n;
	cin >> n;
	ll max_id = 0, max_num = 0;
	for (int i = 1; i <= n; ++i){
		cin >> a[i];
		mp[a[i]] = max(mp[a[i]], mp[a[i] - 1] + 1);
	}
	for(auto w : mp){
		if(max_id < w.second){
			max_num = w.first;
			max_id = w.second;
		}
	}
	vector<ll> ans;
	for (int i = n; i >= 1; --i){
		if(a[i] == max_num){
			ans.push_back(i);
			--max_num;
		}
	}
	cout << ans.size() << endl;
	reverse(ans.begin(), ans.end());
	for(auto w: ans){
		cout << w << " ";
	}
	return 0;
}

CodeForces 1066A Vova and Train

很简单的题,自己写直接交了两发wa,还是队友写的
区间问题需要加强练习,老是对区间问题头疼(对啥都头疼

#define ll long long

int main(){
    ll t;
    cin >> t;
    while(t--){
        ll l, v, x, y;
        cin >> l >> v >> x >> y;
        if(x > y)
            swap(x, y);
		ll num = l / v;
        ll temp = y / v - (x - 1) / v;
        num -= temp;
        cout << num << endl;
    }
        return 0;
}

CodeForces 1539A Contest Start

队友独自写的,和另一个队友推不出来,我不明白她在说什么,结果是道A…
好神奇这道题!完全想不到!证明了我确实应该多刷这种思维题
n - t / x是中间选手的位置
谢谢万能群友的解答,刻烟入肺,我还想是不是什么需要记的结论

#define ll long long

int main(){
    ll k;
    cin >> k;
    while(k--){
        ll n, x, t;
		cin >> n >> x >> t;
		ll m = t / x;
		ll ans = 0;
		if(m >= n){
			ans = (n * (n - 1)) / 2;
		}
		else {
			ans = (n - m) * m + (m * (m - 1)) / 2;
		}
		cout << ans << endl;
	}
        return 0;
}

CodeForces 1575J Jeopardy of Dropped Balls

暴力模拟
谁懂,传参把数组换成变量就能过

int n, m, k;
int g[1100][1100];
int c[1100];

int row[1100];//标记列 反向优化的纪念
// void check(){

// }

int bfs(int st){
    int x = st, y = 1;//x列
    while(y <= n){
        
        if(g[y][x] == 1) {
            g[y][x] = 2;
            ++x;
        }
        else if(g[y][x] == 2){
            ++y;
        }
        else if(g[y][x] == 3){
            g[y][x] = 2;
            --x;
        }
        //cout << x << " " << y << endl;
    }
    return x;
}

int main(){
    cin >> n >> m >> k;
    for (int i = 1; i <= n; ++i){
        for (int j = 1; j <= m; ++j){
            cin >> g[i][j];
        }
    }
    for (int i = 1; i <= k; ++i){
        int t;
        cin >> t;
        cout << bfs(t) << " ";
    }
        return 0;
}

CodeForces 1526B I Hate 1111

当时看到题目我还想是不是题目会有什么玄机,但我觉得不可能这么直白吧
也是考虑了怎么拆,wa后没思路,队友猜测是不是什么规律,被否了,真是规律
两个结论任选其一就能得出答案:
1、n*m-n-m以上的数,n、m可以任意构成
2、1111等可由11、111构成

#include<iostream>
using namespace std;
#define ll long long
int main(){
    int t;
    cin >> t;
    while(t--){
        ll n;
        cin >> n;
        if(n % 11 == 0 || n % 111 == 0){
            cout << "YES" << endl;
            continue;
        }
        else {
            bool flag = false;
            while(n >= 11){
                if(n % 11 == 0) {
                    flag = true;
                    break;
                }
                n -= 111;
            }
            if(flag)
                cout << "YES" << endl;
            else
                cout << "NO" << endl;
        }
    }
    return 0;
}

CodeForces 1208B Uniqueness

这道题用了set wa9,重新看了题是区间,感觉没法做;下来看了题解,好像还是很难的样子…
还有一种方法,但感觉比这个难
记下最后第一个重复的数,保证区间的扩大,取最小的区间确保能被覆盖完(没法说清楚,可能还不熟,待补)

#include<iostream>
#include<map>
using namespace std;
#define ll long long
const int maxn = 1e5 + 5;
ll a[maxn];
map<ll, int> mp;
int main(){
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i){
        cin >> a[i];
    }
    int r = n;
    while(r >= 1){
        if(mp[a[r]] >= 1)
            break;
         ++mp[a[r]];
        --r;
    }
    int ans = INT_MAX;
    for (int i = 1; i <= n; ++i){
        ans = min(ans, r - i + 1);
        ++mp[a[i]];
        while(mp[a[i]] >= 2 && r <= n ){
            ++r;
            --mp[a[r]];
        }
        if(mp[a[i]] >= 2)
            break;
    }
    cout << ans;
    return 0;
}

CodeForces 993A Two Squares

麻了,暴力枚举每个点。没看到有人过,所以根本没考虑,但凡看下题
用数学下来还错了,麻中麻
还是有点难度,不知道怎么遍历菱形
等我深入学了计算几何吧字母太头疼了
挂几个题解在这里
A
B
C

CodeForces 1B Spreadsheet

推出来是二十六进制转十进制,但是我们三都不会大进制转小进制里面的细节,决定放弃
…题读错了还过了四个样例,我说呢;还错得没法改
对比了下思路,果然又复杂又乱orz
被卡吐了

sscanf需要返回值确定是否转化成功

int main() {
	IOS;
	int t;
	cin >> t;
	while(t--){
		string s;
		cin >> s;
		int a, b;
		char c[5], d;
		if(sscanf(s.c_str(),"R%dC%d", &a, &b) == 2){//这个返回值看对不对
			int ans[5], cnt = 0;
			while(b != 0){
				ans[cnt++] = (b - 1) % 26;
				b = (b - 1) / 26;
			}
			for (int i = cnt - 1; i >= 0; --i){
				printf("%c", ans[i] + 'A');
			}
			printf("%d\n", a);
		}
		else if(sscanf(s.c_str(),"%[A-Z]%d", &c, &a)){
			int ans = 0;
			// for (int i = 0; c[i] >= 'A' && c[i] <= 'Z'; ++i){
			// 	ans *= 26;
			// 	ans += (int)(c[i] - 'A' + 1);
			// }
			char *p;//指针的神奇用法
			for(p = c, ans = 0; *p; p++){
				ans = ans * 26, ans += *p - 'A' + 1;
			}
			printf("R%dC%d\n",a, ans);
		}
	}
	return 0;
}

CodeForces 987D Fair

很明显的最短路,和之前写过的一个按权值搜的类似,还剩半小时,回忆+调出来的时间多半不够,放弃了
在这里插入图片描述
写倒是容易,调了半天,又发现思路错了…
摆了
下次认真补

int n, m, k, s;
int v[maxn];
vector<int> g[maxn];
vector<int> mp[maxn];
int dist[maxn][110];
bool vis[maxn];
int anss[maxn];
int temps[maxn];

void dij(int st) {
	queue<int> q;
	re(vis);
	remax(temps);
	for(int i = 1; i <= n; ++i){
		if(v[i] == st) {
			q.push(i);
			temps[i] = 0;
		}
	}
	while (!q.empty()) {
		int id = q.front();
		q.pop();
		if (vis[id])
			continue;
		vis[id] = true;
		for (auto w : g[id]) {
			if (temps[w] > temps[id] + 1) {
				temps[w] = temps[id] + 1;
				q.push(w);
			}
		}
	}
	for(int i = 1; i <= n; ++i){
		if(vis[i] != 0x3f3f3f3f){
			dist[i][st] = temps[i];
		}
	}
}

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
	remax(dist);
	cin >> n >> m >> k >> s;
	for (int i = 1; i <= n; ++i) {
		cin >> v[i];
		mp[v[i]].push_back(i);
	}
	for (int i = 1; i <= m; ++i) {
		int a, b;
		cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	for (int i = 1; i <= k; ++i) {
		dij(i);
	}
	for (int i = 1; i <= n; ++i){
		sort(dist[i] + 1, dist[i] + k + 1);
		int sum = 0;
		for (int j = 1; j <= s; ++j){
			sum += dist[i][j];
		}
		cout << sum << " ";
	}
		return 0;
}

CodeForces 1237B Balanced Tunnel

推了一下,觉得是逆序对,被否了;考虑类似队列+栈的结合,没考虑出来,应该没多难啊
是t宝出的题!
官方题解:记录下每个每个车子出去的时间,如果后面的时间比前面的时间小,说明它超车了。因为先进先出,一定是递减顺序
pair排序加对比取最大值也可以

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn], b[maxn], c[maxn],pos[maxn];

int main(){
	int n;
	cin >> n;
	for(int i = 1; i <= n; ++i){
		cin >> a[i];
	}
	for (int i = 1; i <= n; ++i){
		cin >> b[i];
	}
	for (int i = 1; i <= n; ++i){
		pos[b[i]] = i;
	}
	for (int i = 1; i <= n; ++i){
		c[i] = pos[a[i]];
	}
	int ans = 0;
	int t = 0;
	for (int i = 1; i <= n; ++i){
		if(t > c[i])
			++ans;
		t = max(t, c[i]);
	}
	cout << ans;
	return 0;
}

总之原理一样,但感觉这个更好理解(?)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
pair<int, int> a[maxn];
int main(){
	int n;
	cin >> n;
	for(int i = 1; i <= n; ++i){
		int t;
		cin >> t;
		a[t].first = i;
	}
	for (int i = 1; i <= n; ++i){
		int t;
		cin >> t;
		a[t].second = i;
	}
	sort(a + 1, a + n + 1);
	int ans = 0;
	int t = 0;
	for (int i = 1; i <= n; ++i){
		if(t > a[i].second)
			++ans;
		t = max(t, a[i].second);
	}
	cout << ans;
	return 0;
}

CodeForces 1499C Minimum Grid Path

感觉像个分配的数学问题,卡在分配了,结果是贪心
一直wa4,是因为INT_MAX还是不够大,换成了0x3f3f3f3f3f3f3f3f过的
结合理解

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
#define ll long long
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		ll prea[maxn], a[maxn], preb[maxn], prema[maxn], premb[maxn];
		for (int i = 1; i <= n; ++i){
			cin >> a[i];
			if(i & 1){
				if(i == 1)
					prea[i] = prema[i] = a[i];
				else
					prema[i] = min(prema[i - 2], a[i]), prea[i] = prea[i - 2] + a[i];
			}
			else {
				if(i == 2)
					preb[i] = premb[i] = a[i];
				else
					premb[i] = min(premb[i - 2], a[i]), preb[i] = preb[i - 2] + a[i];
			}
		}
		ll ans = 0x3f3f3f3f3f3f3f;
		for (int i = 2; i <= n; ++i){
			ll temp = 0, k = i / 2;
			if(i & 1){
				temp += prea[i] + (n - k - 1) * prema[i];
				temp += preb[i - 1] + (n - k) * premb[i - 1];
			}
			else {
				temp += prea[i - 1] + (n - k) * prema[i - 1];
				temp += preb[i] + (n - k) * premb[i];
			}
			ans = min(ans, temp);
		}
		cout << ans << endl;
	}
	return 0;
}

怎么说呢,其他的题看了眼题号,暂不涉及哈

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值