AtCoder Beginner Contest 183
A
#include <cstdio>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
printf("%d\n", n >= 0 ? n : 0);
return 0;
}
B
三角形相似,变量直接用double存
#include <cstdio>
using namespace std;
double sx, sy, gx, gy;
int main()
{
scanf("%lf%lf%lf%lf", &sx, &sy, &gx, &gy);
double res = (sy * gx + gy * sx) / (gy + sy);
printf("%lf\n", res);
return 0;
}
C
#include <cstdio>
using namespace std;
const int N = 10;
int n, k, res, t[N][N];
bool vis[N];
void dfs(int u, int cnt, int sum)
{
if(cnt == n && sum + t[u][1] == k)
{
res ++;
return;
}
for(int i = 2; i <= n; ++ i)
{
if(!vis[i])
{
vis[i] = 1;
dfs(i, cnt + 1, sum + t[u][i]);
vis[i] = 0;
}
}
}
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j)
scanf("%d", &t[i][j]);
dfs(1, 1, 0);
printf("%d\n", res);
return 0;
}
D
用\(i\)表示\(i - 1\) -> \(i\)这段时间,维护一下差分序列即可.
#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 2e5 + 20;
LL a[N];
int n, w;
int main()
{
scanf("%d%d", &n, &w);
for(int i = 1; i <= n; ++ i)
{
int s, t, p;
scanf("%d%d%d", &s, &t, &p);
a[s + 1] += p;
a[t + 1] -= p;
}
for(int i = 1; i < N; ++ i)
{
a[i] += a[i - 1];
if(a[i] > w)
{
printf("No\n");
return 0;
}
}
printf("Yes\n");
return 0;
}
E
\(f[i][j]\)表示走到\((i,j)\)的方案数,用前缀和优化一下状态转移,需要做三个前缀和,分别为从左方、上方、左上方转移.
#include <cstdio>
using namespace std;
const int N = 2e3 + 20;
const int MOD = 1e9 + 7;
int n, m;
char s[N][N];
int f[N][N];
int r[N][N], c[N][N], t[N][N];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++ i)
scanf("%s", s[i] + 1);
t[1][1] = c[1][1] = r[1][1] = f[1][1] = 1;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j)
{
if(s[i][j] != '#')
{
if(i - 1 > 0) f[i][j] = (f[i][j] + r[i - 1][j]) % MOD;
if(j - 1 > 0) f[i][j] = (f[i][j] + c[i][j - 1]) % MOD;
if(i - 1 > 0 && j - 1 > 0) f[i][j] = (f[i][j] + t[i - 1][j - 1]) % MOD;
r[i][j] = (r[i - 1][j] + f[i][j]) % MOD;
c[i][j] = (c[i][j - 1] + f[i][j]) % MOD;
t[i][j] = (t[i - 1][j - 1] + f[i][j]) % MOD;
}
else r[i][j] = c[i][j] = t[i][j] = 0;
}
printf("%d\n", f[n][m]);
return 0;
}
F
并查集的启发式合并,按照当前集合的学生所在班级的数目合并
#include <cstdio>
#include <unordered_map>
using namespace std;
const int N = 2e5 + 20;
int n, q;
int fa[N];
unordered_map<int, int> cnt[N];
int find(int x)
{
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
void merge(int x, int y)
{
int fx = find(x), fy = find(y);
if(fx == fy) return;
if(cnt[fx].size() > cnt[fy].size()) swap(fx, fy);
fa[fx] = fy;
for(auto t: cnt[fx])
cnt[fy][t.first] += t.second;
}
int main()
{
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++ i)
{
int x;
scanf("%d", &x);
cnt[i][x] ++;
fa[i] = i;
}
while(q -- )
{
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if(op == 1) merge(a, b);
else
{
int k = find(a);
printf("%d\n", cnt[k][b]);
}
}
return 0;
}
2020.11.21