A 小竹与妈妈
签到题
时间复杂度:O(1)
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, x;
cin >> a >> b >> x;
x -= b;
cout << x / a << endl;
return 0;
}
B 走丢的小竹
签到题:
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N];
int main() {
int n, m, q;
cin >> n >> m >> q;
for (int i = 1; i <= n; i ++ ) {
int x;
cin >> x;
a[x] ++ ;
}
while (q -- ) {
int x;
cin >> x;
cout << n - a[x] << endl;
}
return 0;
}
C 小竹关禁闭
题意:
给定一个数组,你可以选择其中的一些用来组成绳子,但是当你选择了第i个是,后面的k个将无法被选择,问你所能组
成的绳子的最长长度是多少
思路:
一眼dp题
在前k + 1个中选择时,由于他们没有前继状态用来过渡,所以他们初始化为a[i],并以此选择出最大的
k + 1个之后的话,对于每个点就会有两种状态,选/不选
两种状态分别对应这f[i - 1]和f[i - (k + 1)] + a[i]得到最大值即可
集合表示:f[i]表示从前i个中选择所能组成的最大长度
集合属性:MAX
状态转移:i <= k + 1, f[i] = max(f[i], f[i - 1])
i > k + 1, f[i] = max(f[i - 1], f[i - (k + 1)] + a[i])
时间复杂度:O(n)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e3 + 5;
int a[N];
LL f[N];
int main() {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
if(i <= k + 1) f[i] = a[i];
}
for (int i = 1; i <= n; i ++ ) {
f[i] = max(f[i], f[i - 1]);
if(i > k + 1) f[i] = max(f[i], f[i - (k + 1)] + a[i]);
}
cout << f[n] << endl;
return 0;
}
D 游戏购买
题意:
在给定的一个n * m的矩阵中,每个位置不是商店就是住宅,现在你需要从你自己家出发到小胖家,路途中需要买一个
刺激值大于x的游戏,(住宅不可走,商店可以走,并且每个商店可以重复经过),问中间经历的最短路径是多少?
思路 :
这个题的时间限制是5秒,所以直接跑图就可以,从起点和终点分别bfs跑图,最后找到最短的距离
时间复杂度:时间限制很小,都可以过
代码:(直接暴力写,没有任何看点)
#include <bits/stdc++.h>
using namespace std;;
#define inf 0x3f3f3f3f
typedef pair<int, int> PII;
const int N = 2e3 + 5;
int a[N][N];
int dis1[N][N];
int dis2[N][N];
int ans = 0;
PII q[N * N];
bool vis1[N][N];
bool vis2[N][N];
int n, m, x;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
void bfs1(int x, int y) {
queue<PII> qq;
qq.push({x, y});
vis1[x][y] = true;
while (qq.size()) {
auto temp = qq.front();
qq.pop();
int xx = temp.first;
int yy = temp.second;
for (int k = 0; k < 4; k ++ ) {
int i = xx + dx[k];
int j = yy + dy[k];
if(a[i][j] == -1 || vis1[i][j]) continue;
if(i < 1 || i > n || j < 1 || j > m) continue;
dis1[i][j] = dis1[xx][yy] + 1;
qq.push({i, j});
vis1[i][j] = true;
}
}
}
void bfs2(int x, int y) {
queue<PII> qq;
qq.push({x, y});
vis2[x][y] = true;
while (qq.size()) {
auto temp = qq.front();
qq.pop();
int xx = temp.first;
int yy = temp.second;
for (int k = 0; k < 4; k ++ ) {
int i = xx + dx[k];
int j = yy + dy[k];
if(a[i][j] == -1 || vis2[i][j]) continue;
if(i < 1 || i > n || j < 1 || j > m) continue;
dis2[i][j] = dis2[xx][yy] + 1;
qq.push({i, j});
vis2[i][j] = true;
}
}
}
int main() {
cin >> n >> m >> x;
int a1, b1, a2, b2;
cin >> a1 >> b1 >> a2 >> b2;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++) {
cin >> a[i][j];
if(a[i][j] > x) {
q[ ++ ans] = {i, j};
}
}
}
bfs1(a1, b1);
bfs2(a2, b2);
int res = inf;
for (int i = 1; i <= ans; i ++ ) {
int xx = q[i].first, yy = q[i].second;
if(dis1[xx][yy] == 0 || dis2[xx][yy] == 0) continue;
res = min(res, dis1[xx][yy] + dis2[xx][yy]);
}
if(res == inf) cout << "-1" << "\n";
else cout << res << "\n";
return 0;
}
E 寻找小竹
题意:
给定n个路口,n - 1个道路,每个路口都有一个优美值,若是有一对相邻的道路优雅值存在至少两个质因子p和q (p
!= q),则这两个路口就是共同优雅,问:整个城市的最大优雅联通块包含多少个路口
思路:
思路1:如何判断两个数是否有两个不同的公共质因子:
求出gcd,看gcd分解形式是否有两个不同的质因子
如何快速做,预处理每个数的随意的一个之因子(用于分解gcd,这里需要知道对于每个数都会存在一个质因子)
思路2:如何得到最终的答案,树形dp,并查集
参考视频:https://www.bilibili.com/video/BV1NP411c7TM/?p=4&vd_source=12435eebd609bf864d269dac69151858
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e6 + 5;
int a[N];
bool vis[N];
int ans[N];//记录每个连通块的大小
int mnp[N];
int n;
vector<int> e[N];
void init() {
//预处理出范围内的所有的是的一个质因子,用于分解gcd
for (int i = 2; i <= 5000000; i ++ ) {
if(vis[i]) continue;
mnp[i] = i;
//特别注意这里会爆int
for (LL j = (LL)i * i; j <= 5000000; j += i) {
vis[j] = 1;
mnp[j] = i;
}
}
}
int gcd(int a, int b) {
if(b == 0) return a;
return gcd(b, a % b);
}
//判断两者是否具有公共质因子
bool ok(int a, int b) {
int g = gcd(a, b);
vector<int> v;
while (g != 1) {
int mn = mnp[g];
v.push_back(mnp[g]);//素数因子
while (g % mn == 0) g /= mn;
}
return v.size() >= 2;
}
//通过dfs寻找每个点
void dfs(int u, int fa) {
for (auto x : e[u]) {
if(x == fa) continue;
dfs(x, u);
if(ok(a[x], a[u])) ans[u] += ans[x];
}
}
int main() {
init();
cin >> n;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
ans[i] = 1;
}
for (int i = 1; i < n; i ++ ) {
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1, -1);
int res = 1;
for (int i = 1; i <= n; i ++) {
res = max(res, ans[i]);
}
cout << res << endl;
return 0;
}
浙公网安备 33010602011771号