A
题意:
有一个加湿器,每秒都会消耗1单位的水,给加湿器加n次水,求最后一次加水后加湿器的水量。
大致思路:
数据很小,可以遍历每一秒。每次都给加湿器减一单位的水且要保证不会小于零。如果这一秒有加水操作加上即可。并在最后一次加水后输出。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
IOS();
int flag[107];
flag[0] = 0;
for (int i = 1; i <= 100; i++)flag[i] = -1;
int n, x, y;
cin >> n ;
while (n--)
{
cin >> x >> y;
flag[x] = y;
flag[x]--;
}
for (int i = 1; i <= x; i++)
{
flag[i] = max(0, flag[i] + flag[i - 1]);
//cout << flag[i] << '\n';
}
cout << flag[x]+1;
return 0;
}
B
题意:
图中有几个点是桌子,求选出两个桌子来放加湿器,使能加湿的面积最大。然后输出最大面积。
大致思路:
数据很小,枚举这两个点的所有可能,选出最大的面积。(写得有点屎)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int h, w, d, flag[107][107], ans;
string s[17];
vector<pair<int, int>>v;
int t[4][2] = { 1,0,0,1,-1,0,0,-1 };
void dfs(int a, int b, int cnt)
{
if (cnt < 0||flag[a][b]>cnt)return;
if (flag[a][b] == -1 && s[a][b] == '.')ans++;
flag[a][b] = cnt;
for (int i = 0; i < 4; i++)
{
int x = a + t[i][0];
int y = b + t[i][1];
if (x < 0 || y < 0 || x >= h || y >= w )continue;
dfs(x, y, cnt - 1);
}
}
int main()
{
IOS();
cin >> h >> w >> d;
for (int i = 0; i < h; i++)
{
cin >> s[i];
for (int j = 0; j < s[i].size(); j++)
{
if (s[i][j] == '.')v.emplace_back(i, j);
}
}
int as = -1;
for (int i = 0; i < v.size() - 1; i++)
{
for (int j = i + 1; j < v.size(); j++)
{
ans = 0;
memset(flag, -1, sizeof(flag));
dfs(v[i].first, v[i].second, d);
dfs(v[j].first, v[j].second, d);
//cout << v[j].first << ' ' << v[j].second << '\n';
as = max(as, ans);
}
}
cout << as << '\n';
return 0;
}
C
题意:
图中有几个点放置了加湿器,求能加湿的面积。
大致思路:
数据很大且加湿器很多,用dfs会超时,所以用bfs跑一遍。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int h, w, d, flag[1007][1007], ans;
string s[1007];
queue<pair<int, int>>q;
int t[4][2] = { 1,0,0,1,-1,0,0,-1 };
int main()
{
IOS();
cin >> h >> w >> d;
memset(flag, -1, sizeof(flag));
for (int i = 0; i < h; i++)
{
cin >> s[i];
for (int j = 0; j < s[i].size(); j++)
{
if (s[i][j] == 'H')q.emplace(i, j), flag[i][j] = d;
}
}
while (!q.empty())
{
int a = q.front().first;
int b = q.front().second;
q.pop();
for (int i = 0; i < 4; i++)
{
int x = a + t[i][0];
int y = b + t[i][1];
if (x < 0 || y < 0 || x >= h || y >= w || s[x][y] == '#')continue;
//cout << x<<' '<<y << '\n';
if (s[x][y] == '.')
{
//cout << x << ' ' << y << '\n';
int t = flag[a][b] - 1;
//cout << t << '\n';
if (t > flag[x][y])
{
flag[x][y] = t;
if(t>0)q.emplace(x, y);
}
}
}
}
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
//cout << flag[i][j] << '\n';
if (flag[i][j] != -1)ans++;
}
}
cout << ans << '\n';
return 0;
}
D
题意:
求小于等于n的正整数里有多少个因数个数为9的数。
大致思路:
因数个数有个公式:
比如a=b**x+c**y+d**z(b,c,d为质数),那么a的因数个数=(x+1)*(y+1)*(z+1)。
原理很简单,因为关于b有(x+1)种可能,关于c有(y+1)种可能.....所以a的因数有(x+1)*(y+1)*(z+1)种可能。
因数为9时,他的组成有3*3和1*9这两种可能,即找出由两个质数的平方的积或者一个质数的八次方组成的数有几个
因为n很大,所以先找出可能符合情况的质数,再算出符合上述情况的质数组成的数量。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
const int N = 2000000;
int ans[2000007];
vector<ll>v;
int main()
{
IOS();
ll n;
cin >> n;
n = sqrt(n);
//cout << n << '\n';
int sum = 0;
for (int i = 2; i <= n; i++)
{
int flag = 0;
for (int j = 2; j * j <= i; j++)
{
if (i % j == 0)
{
flag = 1;
break;
}
}
if (flag == 0)v.emplace_back(i);
}
for (int i = 0, j = 0; i < v.size(); i++)
{
if (v[i] * v[i] * v[i] * v[i] <= n&&v[i]*v[i]*v[i]<=n)sum++;
int t = n / v[i];
j = upper_bound(v.begin(), v.end(), t) - v.begin();
if (j - i - 1 < 0)continue;
sum += (j - i - 1);
}
cout << sum << '\n';
return 0;
}
E
题意:
给定a,b两个集合,可以随便变换顺序,求使a集合中的点一一匹配b集合中的点时所需的最小权重和。
大致思路:
因为一点到另一点的权重取决于总路径里面权重最大的那一条小路径,所以使用权重最小的边去相连的情况是最优的。可以贪心的先去使用权重小的路径,直到他们的点一一匹配。
flag1【x】记录以x点为祖先,他的儿子中属于a集合的数量。flag2【x】记录以x点为祖先,他的儿子中属于b集合的数量。flag【x】记录以x点为祖先,他的儿子中完成一一匹配的对数,该对数取决于min(flag1[x], flag2lx])。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void IOS()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct Node
{
ll u, v, w;
}r[200007];
ll n, m, k;
int ac[200007];
int flag1[200007], flag2[200007], flag[200007];
int ff(int x)
{
int t1 = x, t2;
while (t1 != ac[t1])
{
t1 = ac[t1];
}
while (x != ac[x])
{
t2 = x;
x = ac[x];
ac[t2] = t1;
}
return x;
}
void un(int x, int y)
{
x = ff(x);
y = ff(y);
ac[y] = x;
flag1[x] += flag1[y];
flag2[x] += flag2[y];
flag[x] += flag[y];
}
bool cmp(Node x, Node y)
{
return x.w < y.w;
}
int main()
{
IOS();
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)ac[i] = i;
for (int i = 1; i <= m; i++)
{
cin >> r[i].u >> r[i].v >> r[i].w;
}
sort(r + 1, r + 1 + m,cmp);
ll ans = 0, x;
for (int i = 1; i <= k; i++)
{
cin >> x;
flag1[x]++;
}
for (int i = 1; i <= k; i++)
{
cin >> x;
flag2[x]++;
}
for (int i = 1; i <= m; i++)
{
ll u = ff(r[i].u);
ll v = ff(r[i].v);
ll w = r[i].w;
if (u==v)continue;
un(u, v);
if (flag[u] < min(flag1[u], flag2[u]))
{
ans += w * (min(flag1[u], flag2[u]) - flag[u]);
flag[u] = min(flag1[u], flag2[u]);
//printf("%d %lld %lld\n", i, w, ans);
}
}
cout << ans;
return 0;
}
/*
6 5 3
1 2 1
3 4 1
1 5 1
4 6 1
5 6 10
1 3 5
2 4 6
*/