Codeforces Round #705 (Div. 2) CD

Codeforces Round #705 (Div. 2)

A. Anti-knapsack

题意: 1到n的数中取一个size最大的集合要求没有任意若干个数的和为k,求这个size

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int main() {
    
    
	int T, n; 
	cin >> T;
	while(T--) {
    
    
		int n, k;
		cin >> n >> k;
		vector<int> ans;
		for(int i = k + 1; i <= n; ++ i) {
    
    
			ans.push_back(i);
		}
		for(int i = (k + 1) / 2; i < k; ++ i) {
    
    
			if(i != k) ans.push_back(i);
		}
		cout << ans.size() << endl;
		for(auto x : ans) {
    
    
			cout << x << " ";
		}
		cout << endl;
	}
	return 0;
}

B. Planet Lapituletti

题意: 时间是lh时lt分制的,问距离给定时间最近的并且镜像仍是合法的时间

思路: 可以发现镜像合法的数只有01258,直接暴力枚举就行

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

map<int, int> mi;
int mp[10] = {
    
    0, 1, 2, 5, 8};
int lh, lm, hh, mm;

inline void init() {
    
    
	mi[0] = 0;
	mi[1] = 1;
	mi[2] = 5;
	mi[5] = 2;
	mi[8] = 8;
}

bool judge(int a, int b, int c, int d) {
    
    
	if(a * 10 + b >= lh) return 0;
	if(c * 10 + d >= lm) return 0; 
	return 1;
}

bool check(int a, int b, int c, int d) {
    
    
	if(!judge(a, b, c, d) || !judge(mi[d], mi[c], mi[b], mi[a])) return 0;
	if(a * 10 + b < hh) return 0;
	if(a * 10 + b == hh && c * 10 + d < mm) return 0;
	
	return 1;
}

int main() {
    
    
	init();
	int T, n; 
	cin >> T;
	while(T--) {
    
    
		
		cin >> lh >> lm;
		scanf("%d:%d", &hh, &mm);
		bool flag = 0;
		for(int aa = 0 ; aa < 5; ++ aa) {
    
    
			if(flag) break;
			for(int bb = 0; bb < 5; ++ bb) {
    
    
				if(flag) break;
				for(int cc = 0; cc < 5; ++ cc) {
    
    
					if(flag) break;
					for(int dd = 0; dd < 5; ++ dd) {
    
    
						if(check(mp[aa], mp[bb], mp[cc], mp[dd])) {
    
    
							cout << mp[aa] << mp[bb] << ":" << mp[cc] << mp[dd] << endl;
							flag = 1;
							break;
						}
					}
				}
			}
		}
		if(!flag) {
    
    
			cout << "00:00\n";
		}
	}
}

C. K-beautiful Strings

题意: 给n,k,一个string,要求找到大于给出string的最小的满足string中每个字母出现的次数都为k的倍数的string

思路: 昨晚的思路是:从后往前枚举每个位置,当前位置要改成比原数大,然后构造符合条件的最小值,能构造就跳出了,
当时是一个细节没处理好然后wa了,早上一改T了,后来看了下string的赋值复杂度是O(len)没太注意,但是改了还是T,下午有事,晚点再补

btw,忽略D的数组问题等,D比C简单啊可恶,也有可能我码真的太不稳不适合写模拟题

upd:和题解一模一样的思路,重写过的,原代码de不出

#include <bits/stdc++.h>
using namespace std;

int cnt[27], ju[27];

inline void init() {
    
    
	for(int i = 0; i < 26; ++ i) {
    
    
		cnt[i] = 0;
	}
}

int n, k;

inline int getNum() {
    
    
	int res = 0;
	for(int i = 0; i < 26; ++ i) {
    
    
		res += (cnt[i] + k - 1) / k;
	}
	return res;
}

inline char getChar() {
    
    
	for(int i = 25; i >= 0; -- i) {
    
    
		if(cnt[i] > 0 && cnt[i] % k != 0) return (char)(i + 'a');
	}
	return 'a';
}

void solve(string s) {
    
    
	int tot = n / k;

	for(int i = n; i >= 1; -- i) {
    
    
//		cout << i << endl;
		cnt[s[i] - 'a'] --;
		int sum = getNum();
		if(sum > tot || s[i] == 'z') continue;
		if(sum == tot && getChar() <= s[i]) continue;
		cout << s.substr(1, i - 1);
		if(sum == tot) {
    
    
			for(int j = 0; j < 26; ++ j) {
    
    
				if(cnt[j] > 0 && cnt[j] % k != 0 && (char)(j + 'a') > s[i]) {
    
    
					cout << (char)(j + 'a');
					cnt[j] ++;
					break;
				}
			}
			for(int j = 0; j < 26; ++ j) {
    
    
				if(cnt[j] % k == 0) continue;
				for(int mm = 0; mm < (k - cnt[j] % k) % k; ++ mm) {
    
    
					cout << (char)(j + 'a');
				}
			}
		}
		else {
    
    



			memset(ju, 0, sizeof ju);
			char ch = (char)(s[i] + 1);
			cout << ch;
			cnt[ch - 'a'] ++;
			int jur = 0;
			for(int j = 1; j < 26; ++ j) {
    
    
				if(cnt[j] == 0) continue;
				ju[j] = (k - cnt[j] % k) % k;
				jur += ju[j] + cnt[j];
			}
			jur += cnt[0];
			ju[0] = n - jur;
			for(int j = 0; j < 26; ++ j) {
    
    
				for(int mm = 0; mm < ju[j]; ++ mm) {
    
    
					cout << (char)(j + 'a');
				}
			}
		}
		return;
	}

	return;
}

int main() {
    
    
	int T;
	cin >> T;
	while(T--) {
    
    
		init();

		cin >> n >> k;
		string s;
		cin >> s;
		if(n % k != 0) {
    
    
			cout << -1 << endl;
			continue;
		}
		s = " " + s;
		for(int i = 1; i <= n; ++ i) {
    
    
			cnt[s[i] - 'a'] ++;
		}

		bool flag = 0;
		for(int i = 0; i < 26; ++ i) {
    
    
			if(cnt[i] % k != 0) {
    
    
				flag = 1;
				break;
			}
		}
		if(!flag) {
    
    
			cout << s.substr(1) << endl;
			continue;
		}

		solve(s);
		cout << endl;
	}

	return 0;
}

D. GCD of an Array

题意: 给一个数列,m次操作,每次将pos位置的数乘上x,问每次操作后数列的总gcd

思路: 因为乘完会很大,取模存数gcd会变,想到分解质因数存质因数,但是当时算空间复杂度怎么算都过不去,好家伙原来可以用map偷(是的我还是不会算这个map最坏情况的复杂度)

mp[i] [j] : 第 i 个数质因数 j 的次数

cnt[i] [j] : 质因数 i 在一个数中出现 j 次的次数

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5 + 10;
const ll mod = 1e9 + 7;

unordered_map<int ,map<int, int> > mp, cnt;
int n, m, a[N];
ll ans = 1;

void getAns(int pos, int x) {
    
    
	for(int i = 2; i * i <= x; ++ i) {
    
    
		while(x % i == 0) {
    
    
			++ mp[pos][i];
			++ cnt[i][mp[pos][i]];
			if(cnt[i][mp[pos][i]] == n) ans = (ans * i) % mod;
			x /= i;
		}
	}
	if(x > 1) {
    
    
		++ mp[pos][x];
		++ cnt[x][mp[pos][x]];
		if(cnt[x][mp[pos][x]] == n) ans = (ans * x) % mod;
	}
}

int main() {
    
    
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
//	int n, m;
	cin >> n >> m;
	for(int i = 1; i <= n; ++ i) {
    
    
		cin >> a[i];
		getAns(i, a[i]);
	} 
	while(m --) {
    
    
		int pos, x;
		cin >> pos >> x;
		getAns(pos, x);
		cout << ans << endl;
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_39602052/article/details/114481013