A
签到
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
void solve() {
int n;
cin >> n;
if (n & 1)cout << (n + 1) / 2;
else cout << n / 2;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}
B
如果存在连续两盏亮着的灯,就灭掉后面那盏
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
void solve() {
int n;
cin >> n;
string s;
cin >> s;
int res = 0;
for (int i = 1; i < n; i++) {
if (s[i] == '1' && s[i - 1] == '1') {
s[i] = '0';
res++;
}
}
cout << res;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}
C
每次可以灭掉连续的K盏灯,所以一共有ans=n-k+1种操作方式,因此会产生2的ans次方种灯的状态,数据较小,不需要快速幂。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
const int mod = 1e9 + 7;
void solve() {
int n, k, res = 1;
cin >> n >> k;
int ans = n - k + 1;
for (int i = 1; i <= ans; i++) {
res = res * 2 % mod;
}
cout << res;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}
D
与C题不同的是,每次操作可以改变任意K盏灯的状态,限制条件减少,重复情况过多,C题方法不适用。打表发现当k为奇数时,可以通过奇数次操作可以使得灭掉奇数盏灯,通过偶数次操作可以使得灭掉偶数盏灯,所有灯的状态都能被实现,即2的n次方种。而当k为偶数时,任意次操作都只能灭掉偶数盏灯,所有只能实现所有情况的一半。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;
const int mod = 1e9 + 7;
void solve() {
int n, k, res = 1;
cin >> n >> k;
if (k == n) {
cout << 2;
return;
}
int ans = n;
if (k%2==0)ans--;
for (int i = 1;i <= ans; i++) {
res = res * 2 % mod;
}
cout << res;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}
E
每次操作都改变两盏灯的状态,因此如果初始时关闭的灯的个数如果为奇数则必然无解。由于不要求最小化操作次数所以直接暴力求解,先遍历每一行,碰的关闭的就直接打开,把需要开启的灯换到最右边,然后遍历最后一列,同样的方法从上到下。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 105;
char a[N][N];
void solve() {
int n, m, sum = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
if (a[i][j] == '0')sum++;
}
}
if (sum & 1) {
cout << -1;
return;
}
int k = 0;
vector<pair<int, int>>q;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (a[i][j] == '0') {
if (j != m) {
a[i][j] = '1';
a[i][j + 1] = (a[i][j + 1] == '0' ? '1' : '0');
k++;
q.push_back({ i,j });
q.push_back({ i,j + 1 });
}
}
}
}
bool qq = false;
for (int i = 1; i <= n; i++) {
if (a[i][m] == '0') {
if (i != n) {
a[i][m] = '1';
a[i+1][m] = (a[i+1][m] == '0' ? '1' : '0');
k++;
q.push_back({ i,m });
q.push_back({ i+1,m});
}
else {
qq = true;
}
}
}
if (qq) {
cout << -1;
return;
}
else {
cout << k << "\n";
for (int i = 0; i < q.size(); i++) {
cout << q[i].first << " " << q[i].second << " ";
if (i%2== 1)cout << "\n";
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}
F和G
这个题的关键应该是不要开灯。对于每个节点来说,如果存在一个与之直连的子节点可以亮着,则该节点必须灭(如果该节点目前还亮着),有两种选择,首选肯定是跟父节点同时灭,其次是跟亮着的子节点同时灭。如果父节点已经灭了或已经没有父节点了,则选择子节点。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
int a[N];
bool vis[N];//记录灯的状态,初始时为0,亮着
vector<int>p[N];
int res = 0;
vector<pair<int, int>>q;
void dfs(int x, int fa) {
int sum = 0,pos=0;//pos用来记录可以亮着的子节点
for (int i = 0; i < p[x].size(); i++) {
if (p[x][i] == fa)continue;
dfs(p[x][i], x);
if (vis[p[x][i]]==0)pos=p[x][i],sum++;
}
if (sum&&vis[x]==0) {
if (fa == 0||vis[fa]==1) {
vis[x] = 1;
vis[pos]=1;
q.push_back({ x,pos});
res++;
}
else {
vis[x] = 1;
vis[fa] = 1;
q.push_back({ x,fa });
res++;
}
}
}
void solve() {
int n;
cin >> n;
int u, v;
for (int i = 1; i < n; i++) {
cin >> u >> v;
p[u].push_back(v);
p[v].push_back(u);
}
dfs(1, 0);
cout << res << "\n";
for (int i = 0; i < q.size(); i++) {
cout << q[i].first << " " << q[i].second << "\n";
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
//cin>>t;
while (t--) {
solve();
}
return 0;
}