2013-2014 ACM ICPC Central European Regional Contest (CERC 13)

这套题的思维量比较少,但是有些题很毒瘤 Orz。

https://codeforces.com/gym/100299

题目按照我过题顺序排的:

L

模拟。

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

int main(){
	int T; cin>>T;
	while(T--){
		int n; cin>>n;
		cout<<(1<<n)-1<<endl;
	}
	return 0;
}

B

模拟,字符串处理。

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

string s[110], tmp[4];
map<string, bool> vis;

int main(){
	int T; cin>>T; getchar();
	while(T--){
		string t; 
		int tot=0;
		while(getline(cin, t)){
			if(t=="what does the fox say?") break;
			s[++tot]=t;
		}
		
		vis.clear();
		rep(i,2,tot){
			int cur=0;
			stringstream ssin(s[i]);
			while(ssin>>t) tmp[++cur]=t;
			vis[tmp[3]]=true;
		}
		
		stringstream ssin(s[1]);
		while(ssin>>t) if(!vis[t]) cout<<t<<' ';
		cout<<endl;
	}
	return 0;
}

F

搜索。

注意题意说的是:一步棋中用一个棋子连续吃掉几个棋子。通过向前或向后的跳跃来吃子也是合法的。

所以我们可以对于棋盘上每一个白棋进行搜索,并找出它们在所有的决策中能够吃掉的最多黑棋,那么这个过程搜索 + 回溯就可以解决了。

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int n=10, N=15;

char g[N][N];

int dfs(int x, int y){
	int res=0;
	for(int i=-1; i<=1; i+=2) for(int j=-1; j<=1; j+=2){
		int kx=i+x, ky=j+y;
		if(kx<1 || kx>n || ky<1 || ky>n) continue;
		if(g[kx][ky]!='B') continue;
		int X=x+2*i, Y=y+2*j;
		if(X<1 || X>n || Y<1 || Y>n) continue;
		if(g[X][Y]!='#') continue;
		// ok
		g[kx][ky]='#';
		res=max(res, dfs(X, Y)+1);
		g[kx][ky]='B';
	}
	return res;
}

int main(){
	int T; cin>>T;
	while(T--){
		rep(i,1,n) rep(j,1,n) cin>>g[i][j];
		int res=0;
		rep(i,1,n) rep(j,1,n) if(g[i][j]=='W'){
			g[i][j]='#';
			res=max(res, dfs(i, j));
			g[i][j]='W';
		}
		cout<<res<<endl;
	}
	return 0;
}

I

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=10010;

int w[N], n;

struct Msg{
	int x, y;
}res[N*55];
int tot;

int main(){
	int T; cin>>T;
	while(T--){
		cin>>n;
		rep(i,1,n) read(w[i]);
		
		tot=0;
		rep(i,1,n){
			int p;
			rep(j,i,n) if(w[j]==i){
				p=j;
				break;
			}

			if(p==i) continue;
			
			while(i!=p){
				if(p-i&1){
					res[++tot]={i, p};
					int mid=p+i>>1;
					rep(j,i,mid) swap(w[j], w[j+(p-i+1)/2]);
					p=mid;
				}
				else{
					res[++tot]={i+1, p};
					int mid=p+i+1>>1;
					rep(j,i+1,mid) swap(w[j], w[j+(p-i)/2]);
					p=mid;
				}
			}
		}
		
		cout<<tot<<endl;
		rep(i,1,tot) printf("%d %d\n", res[i].x, res[i].y);
	}
	return 0;
}

C

注意到当固定右端点 \(i\) 时,其左边最多有 \(log~i\) 段不同的 \(gcd\) 值,而且这个值向左递减,所以我们可以用二分来向左跳并更新答案。

至于区间 \(gcd\) 值用 ST 表维护就行了。

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

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

#define int long long

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=1e5+5;

int n, w[N];

int st[N][25], Log[N];

int gcd(int a, int b){
	return b? gcd(b, a%b): a;
}

void build(){
	rep(i,2,N-1) Log[i]=Log[i/2]+1;
	rep(j,0,20) for(int i=1; i+(1<<j)-1<=n; i++){
		if(!j) st[i][0]=w[i];
		else st[i][j]=gcd(st[i][j-1], st[i+(1<<j-1)][j-1]);
	}
}

int query(int l, int r){
	int k=Log[r-l+1];
	return gcd(st[l][k], st[r-(1<<k)+1][k]);
}

int find(int val, int l, int r){
	int R=r;
	while(l<r){
		int mid=l+r>>1;
		if(query(mid, R)>=val) r=mid;
		else l=mid+1;
	}
	return l;
}

signed main(){
	int T; cin>>T;
	while(T--){
		cin>>n;
		rep(i,1,n) read(w[i]);
		
		build();
		
		int res=0;
		rep(i,1,n){
			int r=i;
			while(r){
				int val=query(r, i); 
				int l=find(val, 1, i);
				res=max(res, (i-l+1)*val);
				r=l-1;
			}
		}
		
		cout<<res<<endl;
	}
	
	return 0;
}

K

我将这题写成大模拟了(悲。

思路很简单:

  • 将所给的关系建成图
  • 若图上存在环,直接用环构造即可。
  • 不存在环则在 DAG 上找到最长链(长度记为 \(sz\)​),构造出的方阵长为 \((sz+1)/2\)。​​
#include<bits/stdc++.h>
using namespace std;

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)

using pii = pair<int, int>;
using ll = long long;

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int n=26, N=35;

int g[N][N];
int m;

int get(char t){
	return t-'a'+1;
}

char rget(int t){
	return t-1+'a';
}

int res[N][N];

int deg[N];
int q[N];
int tt, hh;

int f[N], pre[N];
vector<int> lk; // link
bool topsort(){
	tt=-1, hh=0;
	int cnt=0;
	rep(i,1,n) if(!deg[i]) q[++tt]=i, cnt++, f[i]=1;
	
	while(tt>=hh){
		int u=q[hh++]; 
		rep(v,1,n) if(v!=u && g[u][v]){
			if(--deg[v]==0){
				q[++tt]=v, cnt++;
				if(f[v]<f[u]+1){
					f[v]=f[u]+1;
					pre[v]=u;
				}
			}
		}
	}
	return cnt==n;
}

bool vis[N];
int stk[N], top;
bool gotLoop;
void dfs(int u, int root){
	if(gotLoop) return;
	if(vis[u]){
		if(root==u){
			gotLoop=true;
		}
		return;
	}
	
	stk[++top]=u;
	vis[u]=true;
	
	rep(v,1,n) if(v!=u && g[u][v]){
		dfs(v, root);
		if(gotLoop) return;
	}
	top--;
	vis[u]=false;
}

void check(int sz){
	bool ok=true;
	rep(i,1,sz) rep(j,1,sz-1) if(!g[res[i][j]][res[i][j+1]]) ok=false;
	rep(i,1,sz) rep(j,1,sz-1) if(!g[res[j][i]][res[j+1][i]]) ok=false;
	if(ok) cerr<<"AC"<<endl;
	else cerr<<"WA"<<endl;
}

int main(){
	int T; cin>>T;
	while(T--){
		cin>>m;
		rep(i,1,n) rep(j,1,n) g[i][j]=1;
		while(m--){
			string t; cin>>t;
			int u=get(t[0]), v=get(t[1]);
			g[u][v]=0;
		}

		bool ed=false; int rec; // self loop
		rep(i,1,n) if(g[i][i]) ed=true, rec=i;
		if(ed){
			rep(i,1,20){
				rep(j,1,20) cout<<rget(rec);
				cout<<endl;
			}
			continue;
		}
		
		rep(i,1,n) deg[i]=pre[i]=f[i]=vis[i]=0;
		rep(i,1,n) rep(j,1,n) if(g[i][j]) deg[j]++;

		if(topsort()){
			int u, val=0;
			rep(i,1,n) if(f[i]>val) val=f[i], u=i;
			lk.clear();
			while(u){
				lk.push_back(u);
				u=pre[u];
			}
			reverse(begin(lk), end(lk));
			int sz=(int)lk.size()+1>>1;
			rep(i,1,sz) rep(j,1,sz) res[i][j]=lk[i+j-2];
			rep(i,1,sz){
				rep(j,1,sz) cout<<rget(res[i][j]);
				cout<<endl;
			}

			// check(sz);
		}
		else{
			gotLoop=false;
			rep(i,1,n){
				if(gotLoop) break;
				rep(j,1,n) vis[j]=false;
				top=0;
				dfs(i, i);
			}

			rep(i,1,20) rep(j,1,20) res[i][j]=stk[(i+j)%top+1];
			rep(i,1,20){
				rep(j,1,20) cout<<rget(res[i][j]);
				cout<<endl;
			}
			
			// check(20);
		}
	}
	return 0;
}
posted @ 2021-11-02 20:41  HinanawiTenshi  阅读(47)  评论(0编辑  收藏  举报