VP Educational Codeforces Round 52 (Rated for Div. 2)
A. Vasya and Chocolate
点击查看代码
void solve() {
    i64 s, a, b, c;
    std::cin >> s >> a >> b >> c;
    std::cout << s / c + (s / c / a) * b << "\n";
}
B. Vasya and Isolated Vertices
题意:要求构造\(n\)个点\(m\)条边的图。如果一个点没有边就是孤立点,最少有几个孤立点,最多有几个孤立点。
如果要最少,那么一条边连接两个孤立点。
如果要最多,那么应该选一些点做完全图,这个枚举过来看几个点的边数大于等于\(m\)就行。
点击查看代码
void solve() {
    i64 n, m;
    std::cin >> n >> m;
    if (m == 0) {
    	std::cout << n << " " << n << "\n";
    	return;
    }
    int min = std::max(0ll, n - m * 2);
    int max = 0;
    for (int i = 1; i <= n; ++ i) {
    	if ((i64)i * (i - 1) / 2 >= m) {
    		max = n - i;
    		break;
    	}
    }
    std::cout << min << " " << max << "\n";
}
C. Make It Equal
题意:\(n\)个数,你要把他们变成一样的数,每次选择一个数\(x\),使得\(\sum_{i=1}^{n} \max(0, a_i - x) \leq k\),然后\(a_i = \min(a_i, x)\)。求最少操作次数。
记录每个数的个数从大做到最小数。
每次记录比当前数大的数的个数,一直累加直到大于\(k\)就需要操作一次,然后清空。
点击查看代码
void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    std::map<int, int> cnt;
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    	++ cnt[a[i]];
    }
    int max = *std::max_element(a.begin(), a.end());
    int min = *std::min_element(a.begin(), a.end());	
    i64 ans = 0, sum = 0, tot = 0;
    for (int i = max; i >= min; -- i) {
    	sum += tot;
    	if (sum > k) {
    		++ ans;
    		sum = tot;
    	}
    	tot += cnt[i];
    }
    ans += sum > 0;
    std::cout << ans << "\n";
}
D. Three Pieces
题意:\(n\times n\)的矩阵,\([1, n * n]\)的每个数都恰好出现在一个位置。你要从\(1\)走到\(n\times n\),每个格子可以走任意次,但在走完\([1, i - 1]\)之前走\(i\)是不算的。有三个棋子,一个是马的走法,一个是可以斜着走任意格,一个是横竖走任意格。你一开始可以指定棋子,之后每步也可以改变棋子。要求在步数最少的情况下,改变棋子最少。
因为没玩过国际象棋,以为那个斜着走是每次走一格。硬控两个小时。
记\(dist[0/1/2/][i][j]\)为当前棋子为哪一种当前格子为\(i\)已经走完\(1\)到\(j\)的最短路。建图的话就三个棋子各建一个图。
不过答案要求双关键字,这里有个经典处理方式,就是把第一关键字值乘上很大的值,第二关键字值不变,假设乘上\(m\),就可以直到第一关键字是\(\frac{d}{m}\),第二关键字是\(d \% m\)。
点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n * n);
    int S, T;
    for (int i = 0; i < n * n; ++ i) {
    	std::cin >> a[i];
    	if (a[i] == 1) {
    		S = i;
    	} else if (a[i] == n * n) {
    		T = i;
    	}
    }
    std::vector<std::vector<std::pair<int, int>>> D(3);
    D[0] = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
    for (int i = 1; i < n; ++ i) {
    	D[1].emplace_back(i, i);
    	D[1].emplace_back(i, -i);
    	D[1].emplace_back(-i, i);
    	D[1].emplace_back(-i, -i);
    	D[2].emplace_back(i, 0);
    	D[2].emplace_back(-i, 0);
    	D[2].emplace_back(0, i);
    	D[2].emplace_back(0, -i);
    }
    auto get = [&](int x, int y) -> int {
    	return x * n + y;
    };
    std::vector adj(3, std::vector(n * n, std::vector<int>()));
    for (int i = 0; i < 3; ++ i) {
    	for (int x = 0; x < n; ++ x) {
    		for (int y = 0; y < n; ++ y) {
    			for (auto & [dx, dy] : D[i]) {
    				int nx = x + dx, ny = y + dy;
    				if (nx < 0 || nx >= n || ny < 0 || ny >= n) {
    					continue;
    				}
    				adj[i][get(x, y)].push_back(get(nx, ny));
    			}
    		}
    	}
    }
    const int inf = 1e9, M = 1e5;
    using A = std::array<int, 4>;
    std::priority_queue<A, std::vector<A>, std::greater<A>> heap;
    std::vector dist(3, std::vector(n * n, std::vector<int>(n * n + 1, inf)));
    for (int i = 0; i < 3; ++ i) {
    	dist[i][S][1] = 0;
    	heap.push(A{0, i, S, 1});
    }
    while (heap.size()) {
    	auto [d, t, u, cur] = heap.top(); heap.pop();
    	if (d != dist[t][u][cur]) {
    		continue;
    	}
    	for (int i = 0; i < 3; ++ i) {
    		if (t == i) {
    			for (auto & v : adj[t][u]) {
    				int next = cur + (a[v] == cur + 1);
    				if (dist[t][v][next] > dist[t][u][cur] + M) {
    					dist[t][v][next] = dist[t][u][cur] + M;
    					heap.push(A{dist[t][v][next], t, v, next});
    				}
    			}
    		} else {
    			if (dist[i][u][cur] > dist[t][u][cur] + M + 1) {
    				dist[i][u][cur] = dist[t][u][cur] + M + 1;
    				heap.push(A{dist[i][u][cur], i, u, cur});
    			}
    		}
    	}
    }
    int ans = inf;
    for (int i = 0; i < 3; ++ i) {
    	ans = std::min(ans, dist[i][T][n * n]);
    }
    std::cout << ans / M << " " << ans % M << "\n";
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号