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;
}