2023牛客第二场补题报告D E F G H I K
D-The Game of Eating_2023牛客暑期多校训练营2 (nowcoder.com)
思路
直接从后往前贪心,因为最后一个人没有选择。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m, k;
int a[N];
int g[2010][2010];
void solve() {
cin >> n >> m >> k;
for (int i = 0; i < n; i++) {
for (int j = 1; j <= m; j++) {
cin >> g[i][j];
}
}
set<int> ans;
while (k--) {
int i = k % n;
int id = 1;
for (int j = 1; j <= m; j++) {
if (g[i][j] > g[i][id]) id = j;
}
ans.insert(id);
for (int j = 0; j < n; j++) {
g[j][id] = -INF;
}
}
for (auto i : ans) cout << i << " ";
cout << "\n";
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
E-Square_2023牛客暑期多校训练营2 (nowcoder.com)
思路
因为k的取值只能从0到18,直接枚举然后二分答案即可。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, x, y;
int a[N];
int qpow(int a, int b) {
int ans = 1, base = a;
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
return ans;
}
bool check(int m, int k) {
if (m * m / qpow(10, k) >= x)
return 1;
else
return 0;
}
void solve() {
cin >> x;
for (int i = 0; i <= 18; i++) {
int l = 0, r = 1000000000;
while (l < r) {
int m = l + r >> 1;
if (check(m, i))
r = m;
else
l = m + 1;
}
if (l * l / qpow(10, i) == x) {
cout << l << "\n";
return;
}
}
cout << -1 << "\n";
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
F-Link with Chess Game_2023牛客暑期多校训练营2 (nowcoder.com)
思路
博弈问题,假如我们可以动三个棋子时,首先假设先手动棋子1,那么后手要么动没有动过的棋子,要么将棋子1继续往之前移动的方向移一步;但是假如不移动棋子1,先手完全可以再将棋子1移回原位,这样循环下去先手必定总有操作方法(一个棋子反复横跳),后手必输。为了破局,后手只能移动棋子1,这样我们就可以证明出来,其实双方只有将一个棋子移动到不能移了才会动下一个棋子,这样只需要讨论每个棋子移到两端的奇偶性即可。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m;
int a[N];
void solve() {
int x,y,z;
cin>>n>>x>>y>>z;
int cnt1,cnt2,cnt3;
//0全奇 1全偶 2一奇一偶
if(n%2) {
if(x%2) cnt1=1;
else cnt1=0;
if(y%2) cnt2=1;
else cnt2=0;
if(z%2) cnt3=1;
else cnt3=0;
if(cnt1==0&&cnt2==0&&cnt3==0) {
cout<<"Alice\n";
}
if((cnt1==0&&cnt2==0&&cnt3==1)||(cnt1==0&&cnt2==1&&cnt3==0)||(cnt1==1&&cnt2==0&&cnt3==0)) {
cout<<"Bob\n";
}
if((cnt1==0&&cnt2==1&&cnt3==1)||(cnt1==1&&cnt2==0&&cnt3==1)||(cnt1==1&&cnt2==1&&cnt3==0)) {
cout<<"Alice\n";
}
if(cnt1==1&&cnt2==1&&cnt3==1) {
cout<<"Bob\n";
}
}
else {
cnt1=2;
cnt2=2;
cnt3=2;
cout<<"Alice\n";
}
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
G-Link with Centrally Symmetric Strings_2023牛客暑期多校训练营2 (nowcoder.com)
思路
直接上hash,注意就是对于镜像的字符需要先替换再求hash值。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];
typedef unsigned long long ULL;
ULL h[N], p[N], h1[N],
p1[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
map<int, int> mp;
const int P = 131;
string str;
// 计算子串 str[l ~ r] 的哈希值
ULL get(int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; }
ULL get1(int l, int r) { return h1[r] - h1[l - 1] * p1[r - l + 1]; }
void solve() {
cin >> str;
for (int i = 0; str[i]; i++) {
if (mp.count(str[i]) == 0) {
cout << "NO\n";
return;
}
}
n = str.size();
str = "!" + str;
p[0] = 1;
p1[0] = 1;
for (int i = 1; i <= n; i++) {
h[i] = h[i - 1] * P + str[i];
p[i] = p[i - 1] * P;
}
string s = str;
reverse(str.begin(), str.end());
str = " " + str;
for (int i = 1; i <= n; i++) {
str[i] = mp[str[i]];
}
// cout << str << "\n";
for (int i = 1; i <= n; i++) {
h1[i] = h1[i - 1] * P + str[i];
p1[i] = p1[i - 1] * P;
}
int l = 1;
for (int i = 1; i <= n; i++) {
if (get(l, i) == get1(n - i + 1, n - l + 1)) l = i + 1;
// cout << l << "\n";
}
if (l != n + 1)
cout << "NO\n";
else
cout << "YES\n";
}
signed main() {
IOS;
int t = 1;
string s = "osxzbqdpnu";
for (int i = 0; i < 4; i++) mp[s[i]] = s[i];
for (int i = 4; s[i]; i++) {
if (i % 2 == 0)
mp[s[i]] = s[i + 1];
else
mp[s[i]] = s[i - 1];
}
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
H-0 and 1 in BIT_2023牛客暑期多校训练营2 (nowcoder.com)
思路
操作A相当于取反,操作B相当于加1,所以问题就是变成了给定一个操作区间,每个区间+或-一定数,求结果的问题。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
char s[N];
unsigned int sum[N], sumo[N];
unsigned int ans = 0;
void solve() {
int l, r;
cin >> l >> r;
string ss;
cin >> ss;
l = (l ^ ans) % n + 1, r = (r ^ ans) % n + 1;
if (l > r) swap(l, r);
unsigned int x = 0;
for (int j = 0; ss[j]; j++) x = x << 1 | (ss[j] - '0');
unsigned int add = sumo[r] - sumo[l - 1];
add *= sum[r];
add += x * sum[r] * sum[l - 1];
for (int j = ss.size() - 1; j >= 0; j--) cout << (add >> j & 1);
cout << "\n";
ans = add & ((1ll << ss.size()) - 1);
}
signed main() {
IOS;
int t = 1;
cin >> n >> t;
cin >> (s + 1);
sum[0] = 1;
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1];
if (s[i] == 'A') sum[i] = -sum[i];
}
for (int i = 1; i <= n; i++) {
sumo[i] = sumo[i - 1];
if (s[i] == 'A')
sumo[i] -= sum[i];
else
sumo[i] += sum[i];
}
ans = 0;
for (int i = 1; i <= t; i++) {
solve();
}
}
I-Link with Gomoku_2023牛客暑期多校训练营2 (nowcoder.com)
思路
直接构造,貌似八卦阵比较好构造,但是赛时没想到直接间隔三个’O’放三个个’X’,然后奇偶行交替放置即可。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m;
int a[N];
char g[1010][1010];
void solve() {
cin >> n >> m;
int p;
// if (m % 12 == 0)
// p = 4;
// else
p = 4;
for (int i = 1; i <= n; i++) {
int cnt = 0;
if (m % 2) {
if (i % 2)
g[i][m / 2 + 1] = 'x';
else
g[i][m / 2 + 1] = 'o';
}
int l = 1, r = m;
for (int j = 1; j <= m / 2; j++) {
if (i % 2) {
if ((cnt / (p - 1)) % 2) {
g[i][l] = 'o';
g[i][r] = 'x';
} else {
g[i][l] = 'x';
g[i][r] = 'o';
}
} else {
if ((cnt / (p - 1)) % 2 == 0) {
g[i][l] = 'o';
g[i][r] = 'x';
} else {
g[i][l] = 'x';
g[i][r] = 'o';
}
}
l++;
r--;
cnt++;
// cnt %= p;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << g[i][j];
}
cout << "\n";
}
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
K-Box_2023牛客暑期多校训练营2 (nowcoder.com)
思路
一个很典的dp,直接向左向右不动构造状态转移方程即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f
#define int long long
void solve();
signed main(){
//cin.sync_with_stdio(0);
//cin.tie(0);
int T = 1;
//cin >> T;
while(T--){
solve();
}
return 0;
}
void solve(){
int n;
cin >> n;
vector<int> a(n + 2, 0);
for(int i = 1;i <= n;i++){
cin >> a[i];
}
vector<int> b(n + 2);
for(int i = 1;i <= n;i++){
cin >> b[i + 1];
}
vector<array<int,4>> dp(n + 2);
dp[1][0] = 0;
dp[1][1] = -INF;
dp[1][2] = -INF;
dp[1][3] = -INF;
for(int i = 2;i <= n + 1;i++){
if(b[i] == 1){
dp[i][0] = dp[i - 1][0] + a[i - 2];
dp[i][1] = max(dp[i - 1][0], dp[i - 1][2]) + a[i];
dp[i][2] = max({dp[i - 1][0] + a[i - 1], dp[i - 1][1] + a[i - 2], dp[i - 1][2] + a[i - 1]});//?
dp[i][3] = max(dp[i - 1][1], dp[i - 1][3]) + a[i];
}
else{
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2]);
dp[i][1] = -INF;
dp[i][2] = max(dp[i - 1][3], dp[i - 1][1]);
dp[i][3] = -INF;
}
}
cout << max({dp[n + 1][0],dp[n + 1][1],dp[n + 1][2],dp[n + 1][3]}) << "\n";
}