19级暑假第一场训练赛

题目出自:Codeforces Round #547 (Div. 3)

A. Game 23

https://codeforces.com/problemset/problem/1141/A

#include
using namespace std;
typedef long long ll;
ll n, m;
bool flag;
int cnt;
//数据不大,暴力深搜
void dfs(int now, int step) {
	if (now == m) {
		flag = true;
		cnt = step;
		return;
	}
	if (now > m)return;
	dfs(now * 2, step + 1);
	dfs(now * 3, step + 1);
}
int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n >> m;
	dfs(n, 0);
	if (flag)cout << cnt << endl;
	else cout << -1 << endl;
}

B. Maximal Continuous Rest

https://codeforces.com/problemset/problem/1141/B

作两个周期大小,最大连续序列

#include
using namespace std;
const int N = 4e5 + 50;
int n, a[N];
int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n; bool flag = true;
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
		if (a[i] != 0)flag = false;
	}
	if (flag)return cout << 0, 0;
	for (int i = n; i < 2 * n; i++) a[i] = a[i - n];
	int cnt = 0, msum = 0;
	for (int i = 0; i < 2 * n; i++){
		if (a[i] == 1 && a[i + 1] == 1)
			cnt++;
		if (cnt > msum)
			msum = cnt;
		if (a[i] == 0)
			cnt = 1;
	}
	cout << msum << endl;	
}

C. Polycarp Restores Permutation

https://codeforces.com/problemset/problem/1141/C

做的时候用推导出数学公式但没做特判,导致WA

WA代码:

#include
using namespace std;
const int N = 4e5 + 50;
int n, a[N];
int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n; bool flag = true;
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
		if (a[i] != 0)flag = false;
	}
	if (flag)return cout << 0, 0;
	for (int i = n; i < 2 * n; i++) a[i] = a[i - n];
	int cnt = 0, msum = 0;
	for (int i = 0; i < 2 * n; i++){
		if (a[i] == 1 && a[i + 1] == 1)
			cnt++;
		if (cnt > msum)
			msum = cnt;
		if (a[i] == 0)
			cnt = 1;
	}
	cout << msum << endl;	
}

另一种思路

另p数组首个为0.求出p数组,再得到p数组中最小的值,将p中所有数减掉最小值再加1得到原p。

同时记录原p中每个数出现的次数。超过一次,说明不能还原 。

#include 
using namespace std;
typedef long long LL;
const int MAXN = 2e5 + 10;
LL a[MAXN];
map b;

int main(){
    int n, v;
    cin >> n;
    a[0] = 0;
    LL sum = 0, mmin = 0;
    for (int i = 2;i <= n;i++){
        cin >> v;
        a[i] = a[i - 1] + v;
        sum += a[i];
        mmin = min(mmin, a[i]);
    }
    for (int i = 1;i <= n;i++){
        a[i] = a[i] - mmin + 1;
        if (b[a[i]] == 1 || a[i] > n) {
            cout << -1 << endl;
            return 0;
        }
        b[a[i]] = 1;
    }
    for (int i = 1;i <= n;i++)
        cout << a[i] << ' ' ;
    cout << endl;
    return 0;
}

使用set容器

#include 
using namespace std;
int64_t n, m, mx, i, x, p[222000];
set s;
int main(){
    cin >> n;
    s.insert(0);
    for (i = 1; i < n; i++){
        cin >> x;
        p[i] = p[i - 1] + x;
        m = min(m, p[i]);
        mx = max(mx, p[i]);
        s.insert(p[i]);
    }
    if (mx - m != n - 1 || s.size() < n)cout << -1;
    else for (i = 0; i < n; i++)cout << p[i] + 1 - m << " ";
}

D. Colored Boots

没有做出来,感觉可以二分图做。

https://codeforces.com/problemset/problem/1141/D

贴上dalao题解

思路:

找到所有小写字母,将它们所有的下标位置存入一个数组,然后每次查询相同的字母在s1,s2中的相同字母的位置,

然后输出就好了。

#include
#include
#include
#include
#include
using namespace std;
const int maxn = 2e5+10;
char s1[maxn],s2[maxn];
vector  v1[30],v2[30];
vector  > ans;
int main(void)
{
	int n,i,j,cnt = 0;
	scanf("%d",&n);
	scanf("%s%s",s1+1,s2+1);
	for(i=1;i<=n;i++){
		if(s1[i]>='a'&&s1[i]<='z') v1[s1[i]-'a'].push_back(i);
		else v1[26].push_back(i);
		if(s2[i]>='a'&&s2[i]<='z') v2[s2[i]-'a'].push_back(i);
		else v2[26].push_back(i);
	}
	for(i=0;i<=26;i++){
		while(v1[i].size()>0&&v2[i].size()>0){
			ans.push_back(make_pair(v1[i][v1[i].size()-1],v2[i][v2[i].size()-1]));
			v1[i].pop_back();
			v2[i].pop_back();cnt++;
		}
		while(v1[i].size()>0&&v2[26].size()>0){
			ans.push_back(make_pair(v1[i][v1[i].size()-1],v2[26][v2[26].size()-1]));
			v1[i].pop_back();
			v2[26].pop_back();cnt++;
		}
		while(v1[26].size()>0&&v2[i].size()>0){
			ans.push_back(make_pair(v1[26][v1[26].size()-1],v2[i][v2[i].size()-1]));
			v1[26].pop_back();
			v2[i].pop_back();cnt++;
		}
	}
	printf("%d\n",cnt);
	for(i=0;i

E. Superhero Battle

https://codeforces.com/problemset/problem/1141/E

题意:

有一个怪兽,初始血量为HHH,他的血量变化情况是一个长度为nnn轮的周期。问怪兽会在第几轮死去。
做法

首先如果怪兽血量在一个周期内不曾小于等于000而且每个周期之后怪兽血量增加,直接输出−1。

之后要知道,怪兽在某个完整的周期之前到达x血量,怪兽就撑不过这轮。
这个 \(x\) 的求法就是遍历一遍周期,找到某个时刻怪兽血量消耗最多。

之后就假设怪兽初始血量为 \(H−x\) 看怪兽能撑过几个完整的轮,设这里轮数为 \(k\) ,每轮怪兽血量减少 \(sum\) ,则要满足

\[sum * k + x >= H \]

\[k >= (H - x) / sum \]

所以不等式右面要上取整得到 \(k\) ,之后再 \(O(n)\) 的进行一个周期看怪兽在第几轮死即可。

#include
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
ll a[maxn];
int main() {
    int flag = 0, mark;
    ll h, n, sum = 0, mi = inf;
    cin >> h >> n;
    ll g = h;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum += a[i];
        mi = min(mi, sum);
        g += a[i];
        if (g <= 0 && !flag) mark = i, flag = 1;
    }
    if (flag) return cout << mark << endl, 0;
    if (sum >= 0) return cout << -1 << endl, 0;
    sum = -sum;
    h += mi;
    ll ans = h / sum * n;
    ll cur = h % sum - mi;
    while (cur > 0) {
        for (int i = 1; i <= n; i++) {
            cur += a[i];
            ans++;
            if (cur <= 0) break;
        }
    }
    printf("%lld\n", ans);
    return 0;
}

你可能感兴趣的:(19级暑假第一场训练赛)