B:n个人比赛,比赛规则,1,2比赛,胜者与3比赛,再胜者与4比赛,一次类推,最后得到冠军。故必定进行n - 1次比赛,游戏结束。
现在给定x, y,表示对于其中任何一个人,此人赢了x场或输了y场,问是否有满足该情况的比赛进程成立。
根据比赛特点,对于某个特定的人,要么连胜,要么直接输,这就意味着必定有(x > 0 && y == 0) || (x == 0 && y == 1)
现在我们假设存在满足情况的比赛进程,从1开始构造,取1在第一场比赛中胜,进行模拟,故[2, 2 + x - 1]均输,2 + x必输,于是再次从2 + x开始,使其为胜,重复1的过程,直到比赛次数大于等于n - 1,若合理,则比赛次数为n - 1,否则大于n
tip:对于构造题,几乎可以认为,只要寻找到一个非常特殊的情况,看其在满足限制条件得情况下是否满足题意来确定是否有满足题意得解,所以确定特殊情况(其特殊在哪里,优势),并构造出该特殊情况就成为重中之重。
点击查看代码
#include<bits/stdc++.h>
using i64 = long long;
constexpr int P = 998244353;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int tt = 1; std::cin >> tt;
while(tt--){
int n, x, y; std::cin >> n >> x >> y;
if(x < y){
std::swap(x, y);
}
if(x == 0){
std::cout << -1 << '\n';
continue;
}
if(y){
std::cout << -1 << '\n';
continue;
}
int now = 1, key = 0; std::vector<int> r;
while(now <= n){
r.push_back(now);
if(key == 0){
now += x + 1;
key = 1;
}else{
now += x;
}
}
if(now > n + 1){
std::cout << -1 << '\n';
continue;
}else{
std::vector<int> x(n + 1);
for(auto xx : r){
if(xx <= n){
x[xx] = xx;
}
}
for(int i = 2; i <= n; ++i){
if(x[i] == 0){
x[i] = x[i - 1];
}
std::cout << x[i] << ' ';
}
std::cout << '\n';
}
}
return 0;
}
C:给定大小为n的数组,最多进行n次操作:选择下标为l和r的点,
\[(a[l] + a[r]) \% 2 == 0, a[l] = a[r] \]\[(a[l] + a[r]) \% 2 == 1, a[r] = a[l] \]是否存在某种操作序列,使得数组非递减。
构造题,寻找特殊情况(从终点出发,特殊在非递减,我们特殊至数组所有元素相等),现在考虑在该操作下使得其所有元素相等。
先使a[1] == a[n],然后对于(1, n)内点一定存在其中某种操作使得其等于a[1],故该特殊情况符合构造要求
点击查看代码
#include<bits/stdc++.h>
using i64 = long long;
constexpr int P = 998244353;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int tt = 1; std::cin >> tt;
while(tt--){
int n; std::cin >> n;
std::vector<int> a(n);
for(int i = 0; i < n; ++i){
std::cin >> a[i];
}
if(n == 1){
std::cout << 0 << '\n';
continue;
}
std::vector<std::pair<int, int>> q{{0, n - 1}};
if((a[0] + a[n - 1]) & 1){
a[n - 1] = a[0];
}else{
a[0] = a[n - 1];
}
for(int i = 1; i < n - 1; ++i){
if((a[i] + a[0]) & 1){
q.push_back({0, i});
} else{
q.push_back({i, n - 1});
}
}
std::cout << q.size() << '\n';
for(auto x : q){
std::cout << x.first + 1 << ' ' << x.second + 1 << '\n';
}
}
return 0;
}