Codeforces Global Round 8 题解 (ABCDE)

A. C+=

每次小的那个 += 大的那个

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2;
#define int ll
int a,b,n;
void Solve(){
	cin>>a>>b>>n;
	for(int i=0;;i++){
		if(a<b)swap(a,b);
		if(a>n){cout<<i<<endl; return;}
		b+=a;
	}
}
signed main(){
	int T; cin>>T;
	while(T--)Solve();
	return 0;
}

B. Codeforces Subsequences

首先能想到,答案应该是类似 cccooodddeeefffooorrrccceeesss 的形式,并且连续c,o,d,...的个数应该尽可能接近

因此每次找最少的那个连续字母,并添加这个字母

  • 解释一下为什么要“尽可能接近”。假设有3个f和4个r,如果我添加一个r,那么当前subsequences个数会乘以 \(\dfrac 5 4\),如果增加一个f就会乘以 \(\dfrac 4 3\),后者方案更优
#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2;
#define int ll
int k;
vector<int> a;
void Solve(){
	cin>>k;
	a.assign(10,1); int s=1;
	repeat(i,0,inf){
		if(s>=k)break;
		i%=10;
		s/=a[i];
		a[i]++;
		s*=a[i];
	}
	repeat(i,0,a[0])cout<<'c';
	repeat(i,0,a[1])cout<<'o';
	repeat(i,0,a[2])cout<<'d';
	repeat(i,0,a[3])cout<<'e';
	repeat(i,0,a[4])cout<<'f';
	repeat(i,0,a[5])cout<<'o';
	repeat(i,0,a[6])cout<<'r';
	repeat(i,0,a[7])cout<<'c';
	repeat(i,0,a[8])cout<<'e';
	repeat(i,0,a[9])cout<<'s';
	cout<<endl;
}
signed main(){
	int T=1; //cin>>T;
	while(T--)Solve();
	return 0;
}

C. Even Picture

事实证明(乱搞可得),下面这种排列方法可以切这题

\(n=5\) 的时候)

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2;
#define int ll
int n;
void Solve(){
	int n; cin>>n;
	cout<<3*n+4<<endl;
	repeat(i,1,n+2){
		cout<<i<<' '<<i<<endl;
		cout<<i+1<<' '<<i<<endl;
		cout<<i<<' '<<i+1<<endl;
	}
	cout<<n+2<<' '<<n+2<<endl;
}
signed main(){
	int T=1; //cin>>T;
	while(T--)Solve();
	return 0;
}

D. AND, OR and square sum

事实证明(想想感觉很对),先让 \(a[1]\) 尽可能大,在此基础上让 \(a[2]\) 尽可能大,以此类推,这样答案最优

我不会证明

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2;
#define int ll
int cnt[110];
void Solve(){
	int n; cin>>n;
	repeat(i,0,n){
		int x; cin>>x;
		repeat(j,0,21)cnt[j]+=(x>>j)&1;
	}
	int ans=0;
	repeat(i,0,n){
		int x=0;
		repeat(j,0,21)
		if(cnt[j]>i){
			x|=1<<j;
		}
		ans+=x*x;
	}
	cout<<ans<<endl;
}
signed main(){
	int T=1; //cin>>T;
	while(T--)Solve();
	return 0;
}

E. Ski Accidents

大意:在一个DAG中删除一些点使得不存在长度为2的路径。要求删除的点数不大于 \(\dfrac 4 7 n\)

前半小时切了前四题,后两个小时都没能做出E,枯了。首先这个 \(\dfrac 4 7\) 就很有趣,它正好是一棵三层的满二叉树,删除所有叶子的情况。因此我猜测,对于每个有孙子节点的点,删除其所有孙子,这么写了交上去,wa6。还剩不到半小时,我终于搞出了一个数据hack了自己:

1
10 9
3 4
4 5
4 6
2 6
6 7
6 8
1 8
8 9
8 10

再后来针对数据修改了很久也还是wa6,没办法只能看题解了

首先把所有点分成3类,\(V_0,V_1,V_2\)。其中 \(V_2\) 接下来会被删掉(如果存在边 \((u,v)\),我把 \(u\) 称为 \(v\) 的一个父亲,把 \(v\) 称为 \(u\) 的儿子)

  • \(V_0\) 的父亲只能是 \(V_2\),或者无父亲。也就是说,删掉 \(V_2\)\(V_0\) 就没有父亲了
  • \(V_1\) 的父亲中不能出现 \(V_1\),并且要出现至少一个 \(V_0\)
  • \(V_2\) 的父亲要至少出现一个 \(V_1\)

为确定点的类型,只要按照拓扑序访问每个点。如果父亲中出现一个 \(V_1\) 那就是 \(V_2\),除此之外出现一个 \(V_0\) 那就是 \(V_1\),除此之外都是 \(V_0\)。我们发现,删掉所有 \(V_2\) 后,所有还尚存的边一定连接 \(V_0\)\(V_1\),(不存在 \(V_0-V_0\) 之类的边),完美符合题意。同时,每个 \(V_2\) 都至少连接一个 \(V_1\),为了让 \(V_2\) 尽可能多,那就让 \(V_1\) 连接两个 \(V_2\);同理,让每个 \(V_0\) 连接两个 \(V_1\),这样 \(V_2\) 的比例最高也不会超 \(\dfrac 4 7\),完美符合

这个答案确实是我的“一棵三层的满二叉树删掉叶子”的想法的延伸,但是好难想啊……

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2;
#define int ll
vector<int> a[N],ans;
int w[N];
void Solve(){
	int n,m; cin>>n>>m;
	repeat(i,1,n+1)a[i].clear(),w[i]=0; ans.clear();
	while(m--){
		int x,y; cin>>x>>y;
		a[y].push_back(x);
	}
	repeat(x,1,n+1){
		for(auto p:a[x])
		if(w[p]!=2)
			w[x]=max(w[x],w[p]+1);
		if(w[x]==2)ans.push_back(x);
	}
	cout<<ans.size()<<endl;
	for(auto i:ans)cout<<i<<' '; cout<<endl;
}
signed main(){
	int T=1; cin>>T;
	while(T--)Solve();
	return 0;
}
posted @ 2020-06-19 02:02  axiomofchoice  阅读(185)  评论(0编辑  收藏  举报