2025年4月28日CF补题
Educational Codeforces Round 178 补题
此次排名情况:
- 共1w2+,排名3905,做出ABCD四题。
- Rating+20,当前为
1326。 - 比赛链接
A. Three Decks
签到题
int a,b,c;
cin>>a>>b>>c;
c-=abs(a-b);
c-=max(a,b);
if(c<0) cout<<"NO\n";
else if(c%3==0) cout<<"YES\n";
else cout<<"NO\n";
B. Move to the End
从后往前贪心,看最大的元素和从后往前的第 \(i\) 个元素哪个更大。
int n,m;
struct nod{
ll zhi;
ll id;
friend bool operator <(nod x,nod y){
if(x.zhi!=y.zhi) return x.zhi<y.zhi;
else return x.id<y.id;
}
}a[N];
void solve(){
priority_queue<nod> pq;
map<ll,bool> mp;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].zhi;
a[i].id=i;
pq.push(a[i]);
}
ll sum=0;
for(int i=n;i>=1;i--){
sum+=a[i].zhi;
mp[i]=1;
ll x=pq.top().id;
while(mp[x]&&!pq.empty()){
pq.pop();
x=pq.top().id;
}
if(a[x].zhi>a[i].zhi){
sum-=a[i].zhi;
sum+=a[x].zhi;
cout<<sum<<" ";
sum+=a[i].zhi;
sum-=a[x].zhi;
}else cout<<sum<<" ";
}
cout<<"\n";
}
C. Card Game
判断多种情况即可。
void solve(){
int n;cin>>n;
string s;cin>>s;
if(n==2){
if(s=="AA"||s=="AB") cout<<"Alice\n";
else cout<<"Bob\n";
return;
}
int a1=0,a2=0,a3=0,a4=0,b1=0,b2=0,b3=0,b4=0;
if(s[0]=='A') a1=1;
else b1=1;
if(s[n-1]=='A') a2=1;
else b2=1;
for(int i=1;i<n-1;i++){
if(s[i]=='A') a3=1;
else b3=1;
}
if(s[n-2]=='A') a4=1;
else b4=1;
if(a1&&a2) cout<<"Alice\n";
else if(a1&&b3==0) cout<<"Alice\n";
else if(a2&&a4) cout<<"Alice\n";//a全部大于b//a有n和n-1,
else cout<<"Bob\n";
}
D. Array and GCD
我们可以通过\(+1\) 或 \(-1\) 的操作,在数组的和不变的情况下,更改任意数。
因为需要删除数最少,所以质数和也要最小。看在这个数组和的情况下,最小的质数和是哪一些。要求质数不能相同,所以就从2开始依次取质数。
因为数据范围的原因,不能 \(O(n^2)\) 的筛法,什么筛法最快?欧拉筛,又叫线性筛。
每次测试都筛太慢,预处理即可,我们其实只需要得到前 \(x\) 个质数的和。
根据数据范围可以得知 \(6e6\) 可以处理到 \(5e5\) 的质数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+1;
ll n,a[N];
bool vis[6000000];
ll primes[N], tot; //素数表
vector<ll> v;
void sieve(int n){
v.push_back(0);
vis[1] = true;
for(int i = 2; i <= n; i ++){
if(!vis[i]){
primes[ ++ tot] = i;
v.push_back(v[tot-1]+i);
}
for(int j = 1; i * primes[j] <= n; j ++){
vis[i * primes[j]] = true;
if(i % primes[j] == 0)
break;
}
}
}
void solve(){
cin>>n;ll m=n;
ll sum=0,ans=0,k=1;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
sort(a+1,a+n+1);
ll tmp=v[m];
while(sum<tmp){
sum-=a[k++];
m--;
ans++;
tmp=v[m];
}
cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
sieve(5999999);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
E. Unpleasant Strings
题意:
给定一个字符串 \(s\) 与一些字符串 \(t_i\) ,\(t_i\) 是 \(s\) 子序列,可以 \(t_i\) 后面加字符使得 \(t_i\) 不是 \(s\) 的子序列,最小添加字符是多少?有一个限制,\(s\) 和 \(t\) 以及添加的字符都是给定的前 \(k\) 个字符。
题解:
对每个位置 \(i\) 预处理出对于 \(s[i\sim n]\) 来说,至少要几个字母可以拼出不是子序列的字符串。对每个询问字符串 \(t\) ,找到 \(t\) 作为子序列匹配的末尾位置,直接用之前预处理的答案来回答就好了。
如何预处理?
设 \(nxt[j][i]\) 表示字母 ‘a’ 开始的第 \(j\) 个字母,在 \(i\) 位置之后第一次出现的位置。
\(dp[i]\) 表示对于 \(s[i\sim n]\) ,至少要几个字母可以拼出不是子序列的字符串。
则对从 ‘a’ 开始的前 \(k\) 个字母,若某字母在 \(i\) 的位置之后没有出现过,则 \(dp[i]\) 直接为 \(1\) ,因为直接添加这个字符串就不是子序列。否则 \(dp[i]=min(dp[i],dp[nxt[j][i]]+1)\) ,表示判断先加一个字母 \(j\) ,以此匹配到 \(i\) 之后的下一个字母 \(j\) 所在的位置,再加上此位置的答案是否更优。
高效寻找询问的 \(t\) 作为子序列匹配的末尾位置,也用到了 \(nxt\) 数组。
const ll inf=0x3f3f3f3f;
void solve(){
int n,k,q;
string s;
cin>>n>>k;
cin>>s;
s=" "+s;//下标从1开始
cin>>q;
//相当于int nxt[30][n+5]=-1;
vector<vector<int> > nxt(30,vector<int>(n+5,-1));
for(int i=n-1;i>=0;--i){
for(int j=1;j<=k;j++){
nxt[j][i]=nxt[j][i+1];
}
//nxt[x][i]=字母x在i位置后第一次出现的位置
nxt[s[i+1]-'a'+1][i]=i+1;
}
vector<int> dp(n+10,inf);
for(int i=n;i>=1;--i){
bool f=0;//如果出现了没有某个字母的情况,dp[i]直接=1,不用继续min
for(int j=1;j<=k&&f==0;++j){
if(nxt[j][i]==-1) dp[i]=1,f=1;
else dp[i]=min(dp[i],dp[nxt[j][i]]+1);
}
}
vector<int> ans;
while(q--){
string t;
cin>>t;
t=" "+t;
int p=0;
bool f=0;
for(int i=1;i<t.size()&&f==0;++i){
//如果某个字母没有出现,t就不是s的子序列
if(nxt[t[i]-'a'+1][p]==-1) ans.push_back(0),f=1;
else p=nxt[t[i]-'a'+1][p];
}
if(f) continue;
else ans.push_back(dp[p]);
}
for(int i=0;i<ans.size();i++) cout<<ans[i]<<"\n";
}
F. Numbers and Strings
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k;
map<string,int> mp;
vector<int> v;
int b[15];
int cnt[15];
void solve(){
int n;cin>>n;
cout<<upper_bound(v.begin(),v.end(),n)-v.begin()<<"\n";
}
void push(int x){
string g;
for(int i=0;i<=9;i++){
for(int j=1;j<=cnt[i];j++)
g+=(char)('0'+i);
}
if(!mp.count(g)) mp[g]=x;
else mp[g]=min(mp[g],x);
}
int get(){
int p=-1;
int all=0;
for(int i=0;i<=9;i++) all+=cnt[i];
if(all==0) return 0;
for(int i=1;i<=9;i++){
if(cnt[i]){
p=i;
break;
}
}
if(p==-1) return -1;
int ans=p;cnt[p]--;
for(int i=0;i<=9;i++){
for(int j=1;j<=cnt[i];j++){
ans=ans*10+i;
}
}
cnt[p]++;
return ans;
}
void work(int len){
for(int i=0;i<=9;i++) cnt[i]=0;
for(int i=1;i<=len;i++) cnt[b[i]]++;
if(cnt[9]==len){
cnt[1]++;
cnt[0]+=cnt[9];
int ans=0;
for(int i=1;i<=len;i++) ans=ans*10+9;
push(ans);
return;
}
for(int i=0;i<=cnt[9];i++){
for(int j=0;j<9;j++){
if(!cnt[j]) continue;
int ans=0;;
cnt[9]-=i;
cnt[j]--;
ans=get();
if(ans==-1){
cnt[9]+=i;cnt[j]++;
continue;
}
if(ans==0&&j==0) continue;
ans=(ans*10+j);
for(int k=1;k<=i;k++) ans=ans*10+9;
cnt[9]+=i;cnt[j]++;
for(int k=0;k<=9;k++) cnt[k]*=2;
cnt[9]-=i;cnt[j]--;
cnt[0]+=i;cnt[j+1]++;
push(ans);
cnt[0]-=i;cnt[j+1]--;
cnt[9]+=i;cnt[j]++;
for(int k=0;k<=9;k++) cnt[k]/=2;
}
}
}
void dfs(int u){
if(u>1&&b[u-1]) work(u-1);
if(u==10) return;
for(int i=b[u-1];i<=9;i++){
b[u]=i;
dfs(u+1);
}
}
void init(){
dfs(1);
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++){
v.push_back((*it).second);
}
sort(v.begin(),v.end());
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
init();
while(t--) solve();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#ifdef DEBUG
#include "debug.hpp"
#else
#define debug(...) void(0)
#endif
using i64 = long long;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
string s;
unordered_map<string, int> mp;
auto add = [&](int u) {
if (u == 0 or u >= 999'999'999) return;
auto s = to_string(u) + to_string(u + 1);
ranges::sort(s);
if (not mp.contains(s)) {
mp[s] = u;
} else {
mp[s] = min(mp[s], u);
}
};
auto dfs = [&](this auto& dfs) -> void {
for (int i = 0; i < 10; i += 1) {
auto t = s + char('0' + i);
while (t.size() <= 9) {
add(stoi(t));
t += '9';
}
}
int d = 10;
if (s.empty()) d = 1;
if (s.size() == 1) d = 0;
if (1 < s.size() and s.size() <= 8) d = s.back() - '0';
for (int i = d; i < 10; i += 1) {
s.push_back(i + '0');
dfs();
s.pop_back();
}
};
dfs();
debug(mp.size());
vector<int> ans;
for (auto [x, y] : mp) ans.push_back(y);
ranges::sort(ans);
int t;
cin >> t;
for (int i = 0, n; i < t; i += 1) {
cin >> n;
cout << ranges::upper_bound(ans, n) - ans.begin() << "\n";
}
}
//jiangly的代码
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
void solve() {
int n;
std::cin >> n;
int ans = 0;
for (i64 x = 1; x <= n + 1; x *= 10) {
ans += std::min<i64>((n + 1) / x, 9);
}
ans--;
for (int len = 2; len <= 8; len += 2) {
std::string s;
s += '9';
s += std::string(len / 2, '0');
s += std::string(len / 2 - 1, '9');
for (int x = 1; x <= 8; x++) {
s += '0' + x;
if (std::stoi(s) <= n) {
ans--;
}
s.pop_back();
}
}
for (int len = 3; len <= 7; len += 2) {
std::string s;
s += '9';
s += std::string(len / 2, '0');
s += std::string(len / 2 - 1, '9');
for (int x = 1; x <= 8; x++) {
s += '0' + x;
s += '9';
if (std::stoi(s) <= n) {
ans--;
}
s.pop_back();
s.pop_back();
}
}
int d[9];
for (int i = 0, x = n; i < 9; x /= 10, i++) {
d[i] = x % 10;
}
std::array<std::array<int, 2>, 10> dp {};
for (int i = 8; i >= 1; i--) {
int ni = n;
for (int j = 0; j < i; j++) {
ni /= 10;
}
std::array<std::array<int, 2>, 10> ndp {};
for (int x = 1; x <= 9; x++) {
for (i64 y = x; y <= ni; y *= 10) {
ndp[x][y < ni]++;
}
}
for (int x = 0; x < 10; x++) {
for (int l = 0; l < 2; l++) {
for (int y = x; y <= (l ? 9 : d[i]); y++) {
ndp[y][l || y < d[i]] += dp[x][l];
}
}
}
dp = ndp;
if (i == 2) {
for (int x = 0; x <= 9; x++) {
ans += dp[x][0] * std::min(9, (n % 100 + 1) / 10);
ans += dp[x][1] * 9;
}
}
}
for (int x = 0; x <= 9; x++) {
ans += dp[x][0] * (std::min(d[0], 8) + 1);
ans += dp[x][1] * 9;
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
G. Modulo 3
#include <bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
struct DSU {
vector<pair<int &, int>> his;
int n;
vector<int> f, g, bip;
DSU(int n_) : n(n_), f(n, -1), g(n, 0), bip(n, 1) {}
pair<int, int> find(int x) {
if (f[x] < 0)
return make_pair(x, 0);
pair<int, int> res = find(f[x]);
return make_pair(res.first, res.second ^ g[x]);
}
void set(int &a, int b) {
his.emplace_back(a, a);
a = b;
}
void merge(int a, int b, int &ans) {
pair<int, int> u_res = find(a);
pair<int, int> v_res = find(b);
int u = u_res.first, xa = u_res.second;
int v = v_res.first, xb = v_res.second;
int w = xa ^ xb ^ 1;
if (u == v) {
if (bip[u] && w) {
set(bip[u], 0);
ans--;
}
return;
}
if (f[u] > f[v]) {
std::swap(u, v);
}
ans -= bip[u];
ans -= bip[v];
set(bip[u], bip[u] && bip[v]);
set(f[u], f[u] + f[v]);
set(f[v], u);
set(g[v], w);
ans += bip[u];
}
int timeStamp() {
return his.size();
}
void rollback(int t) {
while (his.size() > t) {
pair<int &, int> &back = his.back();
back.first = back.second;
his.pop_back();
}
}
};
void add(vector<vector<array<int, 2>>> &edges, int p, int l, int r, int x, int y, array<int, 2> e, int N) {
if (l >= y || r <= x)
return;
if (l >= x && r <= y) {
edges[p].push_back(e);
return;
}
int m = (l + r) / 2;
add(edges, 2 * p, l, m, x, y, e, N);
add(edges, 2 * p + 1, m, r, x, y, e, N);
}
void dfs(vector<vector<array<int, 2>>> &edges, int p, int l, int r, int res, DSU &dsu, vector<int> &ans, const vector<int> &k, int N) {
int t = dsu.timeStamp();
int ores = res;
for (size_t i = 0; i < edges[p].size(); ++i) {
int x = edges[p][i][0];
int y = edges[p][i][1];
dsu.merge(x, y, res);
}
if (r - l == 1) {
if (k[l] % 3 != 2) {
ans[l] = k[l] % 3;
} else {
ans[l] = (N - res) % 2 ? 2 : 1;
}
} else {
int m = (l + r) / 2;
dfs(edges, 2 * p, l, m, res, dsu, ans, k, N);
dfs(edges, 2 * p + 1, m, r, res, dsu, ans, k, N);
}
res = ores;
dsu.rollback(t);
}
int main() {
ios::sync_with_stdio(false),cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<int> g(n);
for (int i = 0; i < n; i++) {
cin >> g[i];
g[i]--;
}
const int N = 4 << (31 - __builtin_clz(q));
vector<vector<array<int, 2>>> edges(N);
vector<int> t(n), k(q);
for (int i = 0; i < q; i++) {
int x, y;
cin >> x >> y >> k[i];
x--;
y--;
add(edges, 1, 0, q, t[x], i, , N);
g[x] = y;
t[x] = i;
}
for (int x = 0; x < n; x++) {
add(edges, 1, 0, q, t[x], q, , N);
}
vector<int> ans(q);
DSU dsu(n);
dfs(edges, 1, 0, q, n, dsu, ans, k, n);
for (int i = 0; i < q; i++) {
cout << ans[i] << "\n";
}
return 0;
}

