差点爆零了,最近div2打的越来越艰难了,好多不会累死,脑子完全不够用,上次div3刚上的绿就掉了
Codeforces Round 959(Div. 1 + Div. 2)
A. Diverse Game
链接:Problem - A - Codeforces
思路:
其实就是创建一个和之前不一样的矩阵就好了
解法一:我选择的方法是直接把第一行(或第一列)放在最后一行(或最后一列),其他都往前移就好了,顺序不变
解法二:就是在当前输入的数加一,如果这个数等于最大值就将其变为
1
1
1
代码:
解法一:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 120;
int a[N][N];
void solve() {
int n , m;
cin >> n >> m;
for(int i = 1 ; i <= n ; i++) {
for(int j = 1 ; j <= m ; j++) {
cin >> a[i][j];
}
}
if(n == 1 && m == 1) {
cout << -1 << endl;
return;
}
if(n == 1) {
cout << a[1][m] << " ";
for(int i = 1 ; i < m ; i++) cout << a[1][i] << " ";
cout << endl;
} else if(m == 1) {
cout << a[n][1] << endl;
for(int i = 1 ; i < n ; i++) cout << a[i][1] << endl;
} else {
for(int i = 1 ; i <= m ; i++) cout << a[n][i] << " ";
cout << endl;
for(int i = 1 ; i < n ; i++) {
for(int j = 1 ; j <= m ; j++) {
cout << a[i][j] << " ";
}
cout << endl;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) solve();
return 0;
}
解法二:
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve() {
int n , m;
cin >> n >> m;
int N = n * m , x;
for(int i = 1 ; i <= n ; i++) {
for(int j = 1 ; j <= m ; j++) {
cin >> x;
if(N == 1) x = -1;
else if(x == N) x = 1;
else x++;
cout << x << " ";
}
cout << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) solve();
return 0;
}
B. Fun Game
链接:Problem - B - Codeforces
思路:
我们知道
1
1
1异或
0
或
1
0或1
0或1都会使其改变,而
0
0
0异或其他数都不会使其改变,所以我们要想改变当前这个数,那么这个数之前必须出现
1
1
1,或者他前面都是
0
0
0而他本身是
1
1
1,这样他自己异或他自己也会发生改变
例
1
1
1(位置都是从1开始):
s:010010
t:010000
要使
s
[
5
]
s[5]
s[5]变化,那么就取
[
1
,
2
]
[1,2]
[1,2]这样
s
[
4
]
s[4]
s[4]不变,而
s
[
5
]
s[5]
s[5]发生变化
例
2
2
2:
s:010010
t:000000
要使
s
[
2
]
s[2]
s[2]变化,区间可以取
[
1
,
2
]
[1,2]
[1,2]这样
s
[
2
]
s[2]
s[2]异或本身也会发生变化
综上所述:只要 s s s中的 1 1 1出现的比 t t t中的要早,那么就可以实现相互转换
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve() {
int n;
cin >> n;
string s , t;
cin >> s >> t;
bool falg = true;
for(int i = 0 ; i < n ; i++) {
if(s[i] == '1') break;
if(t[i] == '1') {
falg = false;
break;
}
}
if(falg) cout << "YES" << endl;
else cout << "NO" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) solve();
return 0;
}
C. Hungry Games
链接:Problem - C - Codeforces
思路:
题意大概是给定一个数组,求这个数组中有多少个区间
[
l
,
r
]
[l,r]
[l,r]使得这个区间中所有的数相加不为零,当这个区间数超过
x
x
x之后,那么这一段为零,后面继续加的话,是从零开始加
例如:1、1、1、1 取
x
=
2
x=2
x=2区间
[
0
,
2
]
[0,2]
[0,2]之和为
0
0
0是因为前三个数相加等于
3
3
3大于
2
2
2,所以要归零,而区间
[
0
,
3
]
[0,3]
[0,3]之和为
1
1
1,前面三个数归零了,加上第四个数,所以这个区间之和就是
1
1
1
我们可以逆着求,先求总共有 n ∗ ( n + 1 ) 2 \frac{n*(n + 1)}{2} 2n∗(n+1)种区间,再用总的数量减去区间和为零的区间,从后往前求即可。当然由于可以区间和为零时可以继续往后加,所以后面的会计算多次,所以最好是从后面开始算,然后累加
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve() {
int n , x;
cin >> n >> x;
vector<int> a(n) , s(n + 1);//s为前缀和
for(int i = 0 ; i < n ; i++) {
cin >> a[i];
s[i + 1] = s[i] + a[i];
}
int ans = n * (n + 1) / 2;//总共的区间数
vector<int> dp(n + 1);//用来记录当前位置之后是否出现含有零的区间
dp[n] = 1;
for(int i = n - 1 , j = n + 1 ; i >= 0 ; i--) {
while(s[j - 1] - s[i] > x) j--;//当这个区间超过了x之后,j要往前移,使得这个区间之和的数始终小于等于x
dp[i] = 1 + (j <= n ? dp[j] : 0);
ans -= dp[i] - 1;
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while(t--) solve();
return 0;
}