题目链接:AtCoder Beginner Contest 362
A. Buy a Pen
tag:签到
B. Right Triangle
tag:模拟
C. Right Triangle
tag:贪心
Description:给定\(n\)对整数\(l_i, r_i\);求一个整数序列,满足\(l_i <= x_i <= r_i\),且\(\sum_{i}^{n}x_i = 0\);如果没有则输出\(-1\)。
Solution:先判断是否有解,令\(mi = \sum_{i}^{n}l_i, ma = \sum_{i}^{n}r_i\)。如果\(mi <= 0 且 ma >= 0\)有解,否则无解。
- 先假设所有值都取最小值,则\(sum = mi\),然后开始枚举当前位置的取值,看是否能令\(sum = 0\),否则当前值取最大值,继续向后枚举。
Competing:想到了如何判断是否有解,但是没想到贪心求解。
void solve(){
cin >> n;
int mi = 0, ma = 0;
vector<pii> a(n);
for (int i = 0; i < n; i ++){
int l, r;
cin >> l >> r;
a[i] = {l, r};
mi += l;
ma += r;
}
if (mi > 0 || ma < 0){
cout << "No\n";
}
else{
cout << "Yes\n";
for (int i = 0; i < n; i ++){ // 刚开始假设所有值都取最小值
if (mi == 0){
for (int j = i; j < n; j ++){
cout << a[j].fi << " ";
}
return;
}
mi -= a[i].fi; // 开始选择第i个值
if (a[i].fi <= -mi && -mi <= a[i].se){
cout << -mi << " ";
for (int j = i + 1; j < n; j ++){
cout << a[j].fi << " ";
}
return;
}
mi += a[i].se;
cout << a[i].se << " ";
}
}
}
D. Shortest Path 3
tag:Dijkstra
Description:给定一个图,每个点,边都有权值,求所有从起点\(1\)到\(i\)的路径长度(边的权值 + 点的权值)。
Solution:Dijkstra板子,将权值加上点的权值即可。
void solve(){
cin >> n >> m;
vector g(n + 5, vector<pii>());
vector<int> dis(n + 5, 1e15), st(n + 5);
vector<int> a(n + 5);
for (int i = 1; i <= n; i ++)
cin >> a[i];
for (int i = 0; i < m; i ++){
int x, y, w;
cin >> x >> y >> w;
g[x].eb(w, y);
g[y].eb(w, x);
}
auto dijkstra = [&](int u) -> void{
dis[u] = a[u];
priority_queue<pii, vector<pii>, greater<pii>> qu;
qu.ep(dis[u], u);
while (qu.size()){
auto [w, y] = qu.top();
qu.pop();
if (st[y])
continue;
st[y] = true;
for (auto [ww, yy] : g[y]){
if (a[yy] + ww + w < dis[yy]){
dis[yy] = ww + w + a[yy];
qu.ep(dis[yy], yy);
}
}
}
};
dijkstra(1);
for (int i = 2; i <= n; i ++){
cout << dis[i] << " ";
}
}
E. Count Arithmetic Subsequences
tag: dp
Description:给定一个数组\(a\),求不同长度的等差数列的个数(\(1 <= len <= a.size()\))。a.size() <= 80
。
Solution:因为\(a\)的长度很小,所有我们可以考虑\(dp\)。
-
状态表示:显然需要有长度和公差,然后需要一个位置。所有我们使用\(dp[i][j][k]\),表示终点为\(i\),长度为\(j\),公差为\(k\)的所有等差数列的集合。
-
状态转移:\(dp[i][j][k] += dp[x][j - 1][k], x < i 且 a[k] - a[x] = k\)。
-
初始化:初始化长度为\(2\)的所有答案;注意到公差的范围很大,我们使用\(map\)进行离散化。
int dp[100][100][6500];
map<int, int> d;
void solve(){
cin >> n;
vector<int> a(n);
int cnt = 1;
for (int i = 0; i < n; i ++)
cin >> a[i];
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++){
if (!d[a[i] - a[j]])
d[a[i] - a[j]] = cnt ++; // 离散化
}
for (int i = 0; i < n; i ++){
for (int j = 0; j < i; j ++){
dp[i][2][d[a[i] - a[j]]] ++; // 初始化长度为2的
}
for (int j = 0; j < i; j ++)
for (int k = 3; k <= i + 1; k ++){
dp[i][k][d[a[i] - a[j]]] += dp[j][k - 1][d[a[i] - a[j]]];
dp[i][k][d[a[i] - a[j]]] %= mod;
}
}
for (int k = 1; k <= n; k++){
if (k == 1){
cout << n << " ";
continue;
}
int ans = 0;
for (int i = 0; i < n; i++){
for (int j = 1; j <= cnt; j++){
ans += dp[i][k][j];
ans %= mod;
}
}
cout << ans << ' ';
}
}
标签:AtCoder,qu,Beginner,int,yy,++,362,dp,dis
From: https://www.cnblogs.com/Sakura17/p/18327505