19級暑假第一場訓練賽
題目出自:Codeforces Round #547 (Div. 3)
A. Game 23
https://codeforces.com/problemset/problem/1141/A
#include<bits/stdc++.h> 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<bits/stdc++.h> 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<bits/stdc++.h> 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 <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 2e5 + 10;
LL a[MAXN];
map<LL, int> 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 <bits/stdc++.h>
using namespace std;
int64_t n, m, mx, i, x, p[222000];
set<int64_t> 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<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<utility>
using namespace std;
const int maxn = 2e5+10;
char s1[maxn],s2[maxn];
vector <int> v1[30],v2[30];
vector <pair <int,int> > 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<cnt;i++){
printf("%d %d\n",ans[i].first,ans[i].second);
}
return 0;
}
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<bits/stdc++.h>
#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;
}