Educational Codeforces Round 47 (Rated for Div. 2)

A

https://codeforces.com/contest/1009/problem/A

思路:

用两个指针,一个指向费用,一个指向钱,指向费用的每次右移,指向钱的在满足题意的情况下才右移。

最后输出第二个指针的位置。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

int n, m, k;

vi wal, cost;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	cin >> n >> m;
	cost.resize(n);
	for(int i = 0; i < (int)cost.size(); i++)
		cin >> cost[i];
	wal.resize(m);
	for(int i = 0; i < (int)wal.size(); i++)
		cin >> wal[i];
	int res = 0;
	for(int u = 0, v = 0; u < (int)cost.size() && v < (int)wal.size(); u++){
		if(cost[u] <= wal[v]){
			v++;
			res++;
		}
	}
	cout << res << endl;
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

B

https://codeforces.com/contest/1009/problem/B

思路:

‘1’是万能的,也就是说‘1’是一定可以到达任何位置的。

‘0’和‘2’不是万能的,他们不能相互”穿过“。

用两种方法来获得最小。

第一,把‘2’出现之前的直接sort。

第二,‘2’出现之后, 把每个数进行计数,根据上面的‘定理’,我们知道,‘0’现在是不可能在‘2’的位置了,那只能是‘1’了,所以把一个‘1’放到‘2’的位置(如果有‘1’可以的话),然后再把这个‘2’用‘1’交换,重复这个动作。

根据上面所说的,‘1’可以到达任何位置(或者说任何位置都可以是‘1’),最终会发现第一次出现的‘2’之后的所以‘1’都到了最前面(这里说的最前面是指第一次出现‘2’的位置)。

然后‘2’与‘2’之间的‘0’是死的,动不了的,所以‘2’之间有多少个‘0’就填多少个‘0’。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

int n, m, k;

vi cnt, dif;
string str, ptr;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	cin >> str;
	cnt.resize(3);
	bool found = false;
	int u = 0;
	dif.push_back(0);
	for(int i = 0; i < (int)str.length(); i++){
		if(str[i] == '2'){
			if(!found){
				for(int j = 0; j < cnt[0]; j++)
					str[j] = '0';
				for(int j = cnt[0]; j < i; j++)
					str[j] = '1';
				u = i;
				cnt.clear();
				cnt.resize(3);
				found = true;
			}
			dif.push_back(0);
		}
		if(str[i] == '0')
			dif[dif.size() - 1]++;
		cnt[str[i] - '0']++;
	}
	if(found){
		for(int i = u; i < u + cnt[1]; i++)
			str[i] = '1';
		for(int i = u + cnt[1], j = 1; i < (int)str.length(); j++){
			str[i++] = '2';
			for(int cnt = 0; cnt < dif[j]; cnt++, i++)
				str[i] = '0';
		}
	}
	else{
		for(int i = u; i < u + cnt[0]; i++)
			str[i] = '0';
		for(int i = u + cnt[0]; i < (int)str.length(); i++)
			str[i] = '1';
	}
	cout << str << endl;
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

C

https://codeforces.com/contest/1009/problem/C

思路:

arithmetic mean指的是平均数。

一种很直观想到的是直接对目前的平均数操作,但这样会因为精度误差导致结果错误,即使运算过程有误差优化。

所以采用记录总和最后再除的方法来最大化减少误差。

当d大于0时,要想最大化d的效果就必须选择两端作为i。

相反,要想最小化d的效果就选择中间作为i。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

ll n, m, k;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(7) << fixed;
	cin >> n >> m;
	ll sum = 0;
	while(m--){
		ll x, d;
		cin >> x >> d;
		sum += x * n;
		if(d >= 0)
			sum += d * ((n * (n - 1)) >> 1);
		else
			sum += d * ((((n >> 1) * (1 + (n >> 1))) >> 1) + ((((n - 1) >> 1) * (1 + ((n - 1) >> 1))) >> 1));
	}
	cout << (double)sum / n << endl;
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

D

https://codeforces.com/contest/1009/problem/D

思路:

首先看看是否可以暴力,发现m只有1e5,即使n再大也没法骗到机智的我们。

所以可以直接暴力找i,j。

(有关更好的解法我以后可能会加上去,就先挖个坑了。。。)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

int n, m, k;

queue< pair<int, int> > q;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	cin >> n >> m;
	if(m < n - 1)
		cout << "Impossible" << endl;
	else{
		for(int i = 1; i <= n && m; i++)
			for(int j = i + 1; j <= n && m; j++){
				if(__gcd(i, j) - 1)
					continue;
				q.push(make_pair(i, j));
				m--;
			}
		if(m)
			cout << "Impossible" << endl;
		else{
			cout << "Possible" << endl;
			while(!q.empty()){
				cout << q.front().first << " " << q.front().second << endl;
				q.pop();
			}
		}
	}
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

E

https://codeforces.com/contest/1009/problem/E

思路:

首先考虑dp,dp[i]记录i位的结果。

接下来考虑转移方程,第i位的可能取值有i个,一个个来计算。

当第i位是j时,dp[i] = (dp[i] + dp[i - j] + sum[i - j] * c) % MOD;

在解释c是什么之前,先解释c前面的。

要想i位是j,那么在i - j位的时候必须休息,然后再一直不停地走,这就是dp[i - j] + sum[i - j] * c;

这里直接说明c = (1 << max(0, i - j - 1)),意思是有c种走到i - j的方法。

但是这样还不够,我们发现,这样的复杂度是O(n ^ 2),怎么办呢?

把转移方程换种形式,dp[i] = (∑dp[x] (0 < x < i) + sum[1] * 2 ^ (i - 2) + sum[2] * 2 ^ (i - 3)...)% MOD;

前面的∑可以直接记录,后面的可以发现,求dp[i] 的 是求dp[i - 1] 的两倍 再加上 p[i],这里p[i] = sum[i] - sum[i - 1];

所以就可以O(n)计算出结果了。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 998244353;
const double eps = 1e-8;

int n, m, k;

vll p;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	cin >> n;
	p.resize(n);
	for(int i = 0; i < n; i++)
		cin >> p[i];
	ll res, last, add;
	res = last = add = 0;
	for(int i = 0; i < n; i++){
		add = ((add * 2) % MOD + p[i]) % MOD;
		res = (last + add) % MOD; 
		last = (res + last) % MOD;
	}
	cout << res << endl;
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}


未来可期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值