Codeforces Round #506 (Div. 3) 题解及训练总结

这场可能是因为stl和kmp用的熟,并且前段时间遇到过一道跟取余有关系的题给了思路比较接近,所以abcd都秒了。e题有思路,但是写不出来,f回头想了下觉得挺简单的。四题过后对应rank可以到前30。
总结:

  1. 犯了一个错误1e9的长度当成了9
  2. nex数组初始值nex0=-1,这个不太熟练,浪费了几分钟
  3. e题没有沉下头写
  4. f题没有多想

题解
A
题意:给你一个字符串s,求怎样构造出一个字付串t,使他的子串包含k个s。求最短的t(s长度和k<50)
思路:考虑前缀和后缀最长相同长度。可以暴力,也可以kmp nex数组。
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 1e4+5;
int nex[maxn];
 
void getnex(string s){
	int n = s.size(),i = 0,j = -1;
	nex[0] = -1;
	while(i<n){
		if(s[i]==s[j]||j==-1) nex[++i] = ++j;
		else j = nex[j];
		//cerr<<i<<' '<<j<<'\n';
	}
}
 
int main(){
	IO;
	int n,k;cin>>n>>k;
	string s;cin>>s;
	getnex(s);
	//cerr<<"!@3"<<'\n';
	int pos = nex[n];
	string t = s;
	k--;
	//cerr<<"!@3"<<'\n';
	while(k--){
		for(int i = pos;i<n;i++) t+=s[i];
	}
	cout <<t<<'\n';
 
 
 
 
 
	return 0;
}

B.
题意:给你一个长度n(2e5)的递增数组,让你找一个子串,它的2*ai>=ai+1。
思路:On的跑一遍,满足条件cnt++,此外cnt=0。
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 
int main(){
	IO;
	int n;cin>>n;
	vector<int>a(n);
	forn(i,n)  cin>>a[i];
	int cnt = 1,ans = 1;
	for1(i,n-1){
		if(a[i]<=a[i-1]*2) cnt++;
		else cnt = 1;
		ans = max(ans,cnt);
	}
	cout << ans <<'\n';
	return 0;
}

C
题意:给你n(2e5)个区间,让你删掉一个区间,使得区间重合部分最大。
思路:用multiset
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 
int main(){
	IO;
	int n;cin>>n;
	vector<pair<int,int> >a(n);
	multiset<int>l,r;
	forn(i,n){
		cin>>a[i].first>>a[i].second;
		l.insert(a[i].first);
		r.insert(a[i].second);
	}
	int ans = 0;
	forn(i,n){
		l.erase(l.find(a[i].first));
		r.erase(r.find(a[i].second));
		int x = *l.rbegin(),y = *r.begin();
		ans = max(ans,y-x);
		l.insert(a[i].first);
		r.insert(a[i].second);	
	}
	cout << ans <<'\n';
	return 0;
}

D
题意:给你n个数(2e5),和一个k(1e9)。现在让你将任意两个数组合,比如12和23可以组合成1223和2312,如果组合过的数可以整除k,那么算是一个好数。看有多少个好数。
思路:很显然一个组合有数x10^leny
和y组成,那么只要知道x
10^leny的余数和y的余数相加是否为0或k就可以。
预处理每个数字*10^(1-10)的余数,然后对应加起来。坑点比较多。
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 
map<ll,int>b[15];
 
int main(){
	IO;
	int n,k;cin>>n>>k;vector<int>a(n);
	forn(i,n){
		cin>>a[i];
		ll x = a[i];
		for1(j,10){
			x*=10;
			x%=k;
			b[j][x]++;
			//cerr<<x<<' '<<y<<'\n';
		}
	}
	ll ans = 0;
	forn(i,n){
		int len = 0,x = a[i];
		while(x){
			x/=10;
			len++;
		}
		x = a[i]%k;
		int y = k-x;
		y%=k;
		ans+=b[len][y];
		ll z = a[i];
		while(len--){
			z*=10;
			z%=k;
		}
		x = z%k;
		if(x==y) ans--;
	}
	cout << ans <<'\n';
	return 0;
}

E
题意:给一棵树,n个点,n-1条边每个边权值为1。现在添加k条边使得所有点与1点距离小于等于2,求k的最小值。(n1e5)
思路:贪心 每次取距离1点最长距离点的父亲节点与1相连。
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 2e5+5;
int ans;
vector<int>e[maxn],dis(maxn);
 
int dfs(int u,int pre,int d){
	dis[u] = d;
	bool ok = 0;
	for(auto x:e[u]){
		if(x==pre) continue;
		dfs(x,u,d+1);
		if(dis[x]>2){
			ok = 1;
			dis[u] = 1;
			dis[pre] = 2;
		}
	}
	ans+=ok;
}
 
int main(){
	IO;
	int n;cin>>n;
	forn(i,n-1){
		int x,y;cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
	}
	dfs(1,1,0);
	for1(i,4)cerr<<dis[i]<<' ';
	cerr<<'\n';
	cout << ans<<'\n';
	
	
	
	return 0;
}

F
题意:给你a个红色砖块和b个蓝色砖块,要求用完a和b拼成一个长方形(可以是正方形),并且满足里面的仅由红色砖或蓝色砖可组成一个矩形。求此矩形的最小周长。
思路:根号下枚举a,b和大矩形的宽。通过大矩形宽来找a或b中满足条件的最大宽(logn可以优化为On),然后记录一次ans,取最小。在来找最大宽的时候,我们可以根据上一次的结论来确定的新的最大宽为多少。
代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(ll i=0;i<n;i++)
#define for1(i,n) for(ll i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 
int main(){
	IO;
	ll a,b;cin>>a>>b;		
	ll n = sqrt(a),m = sqrt(b);
	vector<int>aa,bb;
	for1(i,n)if(a%i==0) aa.push_back(i); 
	for1(i,m)if(b%i==0) bb.push_back(i);
	ll sum = a+b;int x = sqrt(sum);
	ll ans = 0x3f3f3f3f3f3f3f3f;
	int p1,p2;p1 = p2 = 0;
	for1(h,x)if(sum%h==0){
		ll w = sum/h;
		while(p1<aa.size()&&aa[p1]<=h)p1++;
		while(p2<bb.size()&&bb[p2]<=h)p2++;
		if(p1&&a/aa[p1-1]<=w) ans = min(ans,2*(h+w));
		if(p2&&b/bb[p2-1]<=w) ans = min(ans,2*(h+w));
	}
	cout << ans<<'\n';
	return 0;
}
posted @ 2019-08-02 21:09  AlexPanda  阅读(158)  评论(0编辑  收藏  举报