目录
E - Revenge of "The Salary of AtCoder Inc."
D - ABC Puzzle
tag:搜索,剪枝,dfs
思路:
赛中的时候就大概算了4^25,感觉这个复杂度dfs基本不可能,所以我就放弃了,但是我们仔细观察可以发现,他每一行和每一列的合法情况不多,因为ABC只能出现一次,而且还要满足给出的两个字符串,粗略估计一下大概为( * 2 ) ^ 5,因此我们再加上剪枝肯定是可以满足的。
题解:
初始化为'.',然后dfs一遍,每次判断是否满足当前条件,如果不满足则直接返回,完成剪枝操作,避免重复计算加大计算量,用到了大量的变量来判断条件,这个题比较考验码力,具体如代码所示。
// 加油昂!!!
// Problem: D - ABC Puzzle
// Contest: AtCoder - Panasonic Programming Contest 2023(AtCoder Beginner Contest 326)
// URL: https://atcoder.jp/contests/abc326/tasks/abc326_d
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
string R, C;
char p[5][5];
bool fx[5], fy[5];
bool fx1[5][3], fy1[5][3];
bool flag = false;
int sum[5];
bool f[5];
void dfs(int x, int y)
{
if (flag) return;
if (x == n)
{
cout << "Yes" << "\n";
flag = true;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << p[i][j];
cout << "\n";
}
return ;
}
for (int i = 0; i < 3; i++)
{
char c = 'A' + i;
if (fx1[x][i] == true) continue;
if (fy1[y][i] == true) continue;
if (!fx[x] && c != R[x]) continue;
if (!fy[y] && c != C[y]) continue;
p[x][y] = c;
sum[x] += (i + 1);
bool f1 = fx[x], f2 = fy[y], f3 = fx1[x][i], f4 = fy1[y][i];
fx[x] = fy[y] = fx1[x][i] = fy1[y][i] = true;
if (y + 1 < n) dfs(x, y + 1);
else if (sum[x] == 6) dfs(x + 1, 0);
sum[x] -= (i + 1);
fx[x] = f1, fy[y] = f2, fx1[x][i] = f3, fy1[y][i] = f4;
p[x][y] = '.';
}
if (y + 1 < n) dfs(x, y + 1);
else if (sum[x] == 6) dfs(x + 1, 0);
}
void solve()
{
cin >> n;
cin >> R >> C;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
p[i][j] = '.';
}
dfs(0,0);
if (!flag) cout << "No\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
E - Revenge of "The Salary of AtCoder Inc."
tag:概率,期望
解答:
每一个数能够由前面所有的数转移得到,第一个数得到的概率是,第二个数是,……,以此类推,可以发现递推公式,然后答案为。
// 加油昂!!!
// Problem: E - Revenge of "The Salary of AtCoder Inc."
// Contest: AtCoder - Panasonic Programming Contest 2023(AtCoder Beginner Contest 326)
// URL: https://atcoder.jp/contests/abc326/tasks/abc326_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 3e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
int p[N];
int quick_mi(int a, int b, int p)
{
int ans = 1 % p;
while(b)
{
if (b & 1) (ans *= a) %= p;
(a *= a) %= p;
b >>= 1;
}
return ans;
}
void solve()
{
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
int ni = quick_mi(n, mod - 2, mod);
p[0] = ni;
int ans = 0;
for (int i = 0; i < n; i++)
{
if (i) (p[i] = p[i - 1] * ni + ni) %= mod;
(ans += p[i] * a[i] % mod) %= mod;
if (i) (p[i] += p[i - 1]) %= mod;
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
F - Robot Rotation
tag:DFS
题解:
这个题可以看出是按照下标奇偶性分开,转换为一个问题,给定一个长度为n/2的序列,能否通过改变符号使之和等于给定数字,并且要给出改变了哪一些,只要我们知道了改变的是什么,那么方向的改变也很好求。数据范围可以看出不能直接使用dfs,因为一半的序列长度都是40。所以需要双向dfs,但是我这里写的这个拆开的写法应该不算是双向dfs,我估摸复杂度应该也是和不拆开一样的,但是过了,需要dfs四次,然后再遍历一遍dfs出的所有解,再用4个map存下来,并遍历其中map和其对应的map求解,如果加起来满足答案,那么就将其存储下来结束循环,否则就不行具体见代码:
// 加油昂!!!
// Problem: F - Robot Rotation
// Contest: AtCoder - Panasonic Programming Contest 2023(AtCoder Beginner Contest 326)
// URL: https://atcoder.jp/contests/abc326/tasks/abc326_f
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, X, Y;
int res[4];
unordered_map<int,vector<int>> mp[4];
vector<int> a(85);
vector<int> now[4];
int all[4];
void dfs(int i)
{
int ne = i % 4;
if ((int)now[ne].size() == res[ne])
{
mp[ne][all[ne]] = now[ne];
return ;
}
all[ne] += a[i];
now[ne].push_back(1);
dfs(i + 4);
all[ne] -= a[i] * 2;
now[ne][now[ne].size() - 1] = -1;
dfs(i + 4);
now[ne].erase(--now[ne].end());
all[ne] += a[i];
}
void solve()
{
cin >> n >> X >> Y;
for (int i = 0; i < 4; i++)
{
res[i] = (n + 4 - i - 1) / 4;
}
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
dfs(0);
dfs(1);
dfs(2);
dfs(3);
vector<int> ansy[2];
bool f = false;
for (auto &[x,y] : mp[0])
{
if (mp[2].count(Y - x))
{
ansy[0].insert(ansy[0].end(), y.begin(), y.end());
ansy[1].insert(ansy[1].end(), mp[2][Y - x].begin(), mp[2][Y - x].end());
f = true;
break;
}
}
if (!f)
{
cout << "No\n";
return ;
}
vector<int> ansx[2];
f = false;
for (auto &[x,y] : mp[1])
{
if (mp[3].count(X - x))
{
//reverse(y.begin(), y.end());
ansx[0].insert(ansx[0].end(), y.begin(), y.end());
//reverse(mp[3][X - x].begin(), mp[3][X - x].end());
ansx[1].insert(ansx[1].end(), mp[3][X - x].begin(), mp[3][X - x].end());
f = true;
break;
}
}
if (!f)
{
cout << "No\n";
return ;
}
cout << "Yes\n";
int last = 1;
for (int i = 0; i < n; i++)
{
if (i % 2 == 0)
{
int j = i / 2;
int now = j / 2;
if (last == 1)
{
if (ansy[j % 2][now] == 1) cout << "L";
else cout << "R";
}
else
{
if (ansy[j % 2][now] == 1) cout << "R";
else cout << "L";
}
last = ansy[j % 2][now];
}
else
{
int j = i / 2;
int now = j / 2;
if (last == 1)
{
if (ansx[j % 2][now] == 1) cout << "R";
else cout << "L";
}
else
{
if (ansx[j % 2][now] == 1) cout << "L";
else cout << "R";
}
last = ansx[j % 2][now];
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}