Codeforces Round #578 (Div. 2)

Codeforces Round #578 (Div. 2) 简易题解

A. Hotelier

题意

就是模拟客人进酒店
有n个客人有动作
L表示找到左边第一个空的住进去
R表示找到右边第一个空的住进去
数字表示第几间房子的人走了

题解

模拟即可

#include<bits/stdc++.h>
using namespace std;
int n, ans[15];
int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; i ++){
		char ch;
		cin >> ch;
		if(ch == 'L'){
			for(int j = 0; j < 10; j ++){
				if(!ans[j]){
					ans[j] = 1;
					break;
				}
			}
		}else
		if(ch == 'R'){
			for(int j = 9; j >= 0; j --){
				if(!ans[j]){
					ans[j] = 1;
					break;
				}
			}
		}else{
			ans[ch - '0'] = 0;
		}
	}
	for(int i = 0; i < 10; i ++) cout << ans[i];
	return 0;
}

B. Block Adventure

题意

一个人在跳柱子,每个柱子有一定的高度,那个人有个背包,可是塞无限多的东西,一开始有一定数量的垫脚石,每次可以把石柱砍掉一节塞进包里或从包里拿出来垫脚,要跳到下一个柱子仅当高度差不超过k,问是否可以跳到终点

贪心即可

#include<bits/stdc++.h>
using namespace std;
int n, a[1005], t, m, k;
int main(){
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--){
		int F = 0;
	cin >> n >> m >> k;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	for(int i = 1; i < n; i ++){
		int tt = max(a[i + 1] - k, 0);
		m += a[i] - tt;
		if(m < 0){
			F = 1;
			break;
		}
	}
	if(F) cout << "NO" << endl;
	else cout << "YES" << endl;
	}
	return 0;
}

C. Round Corridor

题意

比较清晰,就是有两圈,里面一圈平均分为n段,外面一圈平均分为m段,问两端直接是否相同

题解

他们的分界个数就是gcd,然后分一下块就可以了

#include<bits/stdc++.h>
#define int long long
using namespace std;
long long gcd(long long a, long long b){
	return b? gcd(b, a % b):a;
}
long long n, m, q, a, b, c, d;
signed main(){
	ios::sync_with_stdio(false);
	cin >> n >> m >> q;
	long long d = gcd(n, m);
	int nn = n / d, mm = m / d;
	while(q --){
		
		cin >> a >> b >> c >> d;
		if(a == 1) b = (b - 1) / nn + 1;
		else b = (b - 1) / mm + 1;
		
		if(c == 1) d = (d - 1) / nn + 1;
		else d = (d - 1) / mm + 1;
		
		if(b == d) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

D. White Lines

大意

给出一个 n ∗ n n*n nn的黑白矩阵,可以将一个 k ∗ k k*k kk的矩阵变为白色,问最多可以产生多少条白线(行或列只有白色)

题解

行列分开做,最后加在一起即可

#include<bits/stdc++.h>
using namespace std;
int n, m, k, a[5005][2005], h[2005][2005], l[2005][2005], ans1[2005][2005], ans2[2005][2005];
int main(){
	ios::sync_with_stdio(false);
	cin >> n >> k;
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++){
			char ch;
			cin >> ch;
			if(ch == 'B') a[i][j] = 1;
		}
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			h[i][j] = h[i][j - 1] + a[i][j];//做第i行的前缀和
	
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			l[i][j] = l[i][j - 1] + a[j][i];//做第i列的前缀和
	
	int ans = 0;
	for(int i = 1; i <= n; i ++){//先把能加的加了
		if(h[i][n] == 0) ans ++;
		if(l[i][n] == 0) ans ++;
	}
	int tt = 0;
	for(int i = 1; i <= n; i ++){//先做列,可以理解为把一个矩阵不断向右移,可以增加的白线列数
		tt = 0;
		for(int j = 1; j <= n; j ++){
			 if(l[j][i] - l[j][max(i - k, 0)] == l[j][n] && l[j][n]) tt ++;
			 if(j > k && l[j - k][i] - l[j - k][max(i - k, 0)] == l[j - k][n] && l[j - k][n]) tt --;
			 ans1[i][j] = tt;
		}
	}
	
	for(int i = 1; i <= n; i ++){//同上
		tt = 0;
		for(int j = 1; j <= n; j ++){
			 if(h[j][i] - h[j][max(i - k, 0)] == h[j][n] && h[j][n]) tt ++;
			 if(j > k && h[j - k][i] - h[j - k][max(i - k, 0)] == h[j - k][n] && h[j - k][n]) tt --;
			 ans2[i][j] = tt;
		}
	}	
	int anss = 0;
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			anss = max(anss, ans1[i][j] + ans2[j][i]);//更新答案
	cout << ans + anss;
	return 0;
}

E. Compress Words

题意

题意比较清楚了,看样例都猜得出来

题解

大力hash(自然溢出会被卡)

#include<bits/stdc++.h>//codef****
#define int long long
#define N 8000005
#define mod 19260817//这个模数可以过(很暴力
using namespace std;
int n;
long long pw[N], ha[N], haa[N];
string st;
int cg(char x){
	return x;
}
signed main () {
  ios::sync_with_stdio(false);
  cin >> n;
  int L = 0;
  pw[0] = 1;
  for(int i = 1; i <= 4000000; i++) pw[i] = pw[i - 1] * 16631 % mod;
  for(int i = 1; i <= n; i++) {
  	cin >> st;
  	int len = st.length();
  	for(int j = 1; j <= len; j++) ha[j] = (ha[j - 1] * 16631 % mod + cg(st[j - 1]))% mod;
  	
  	int l;
  	for(l = min(L, len); l; l--) {
  	  int x = ha[l];
	  int y = (haa[L] - haa[L - l] * pw[l] % mod + mod) % mod;
	  if(x == y) break;
	}
	for(int j = l; j < len; j++) cout << st[j], haa[L + j - l + 1] = (haa[L + j - l] * 16631 % mod + cg(st[j])) % mod;
	L += (len - l);
  }
}

F. Graph Traveler

题意

比较复杂,自行理解吧
Gildong正在试验一个有趣的Graph Traveler,具体来说,这个Graph Traveler是个由n个编号为1-n的点构成的有向图,第i个点有 m i m_i mi条出边,边到达的点分别被记为 e i [ 0 ] , e i [ 1 ] . . . e i [ m i − 1 ] e_i[0],e_i[1]...e_i[m_i-1] ei[0],ei[1]...ei[mi1].每个点还有点权 k i k_i ki

现在有 q q q个询问,每个询问要求从某个点开始,初始有个点权 c c c,每次到一个点 i i i(起点也算)就把点权 c c c加上 k i k_i ki ,然后走 i i i的出边 e i [ x ] ( x ≡ c m o d &ThinSpace;&ThinSpace; m i ) e_i[x](x \equiv c\mod m_i) ei[x](xcmodmi).可以发现这个过程是会一直进行下去的.现在问每次这样走,图上有多少个点会被经过无限次

题解

发现有用的状态只有 l c m ( 1 , 2 , 3 , 4 , 5 , . . . . , 10 ) ∗ n lcm(1,2,3,4,5,....,10) * n lcm(1,2,3,4,5,....,10)n个,然后暴力找环即可
我的写法比较巧妙,自行理解吧

#include<bits/stdc++.h>
#define mod 2520
#define N 1005
using namespace std;
int dep, f[N][mod], ck[N], n, k[N], q;
vector<int> a[N];
int dfs(int x, int y) {
	if(f[x][y] > 0) return f[x][y];
	if(f[x][y] < 0) {
		int sz = 0;
		for(int i = 1; i <= n; i ++) sz += (ck[i] <= f[x][y]);
		return f[x][y] = sz;
	}
	f[x][y] = ck[x] = -- dep;
	int yy = (y + k[x]) % a[x].size();
	return f[x][y] = dfs(a[x][yy], (y + k[x]) % mod);
}
int main() {
  ios::sync_with_stdio(false);
  cin >> n;
  for(int i = 1; i <= n; i ++) cin >> k[i], k[i] = (k[i] % mod + mod) % mod;
  for(int i = 1; i <= n; i ++) {
  	int x, y;
  	cin >> x;
	while(x --) cin >> y, a[i].push_back(y);
  }
  cin >> q;
  while(q --) {
  	int x, y;
    cin >> x >> y;
    y = (y % mod + mod) % mod;
    cout << dfs(x, y) << endl;
  }
  return 0;
}
posted @ 2019-08-12 15:09  lahlah  阅读(18)  评论(0编辑  收藏  举报