A.
题意:有1~n一排数,每天可以搬运一个东西到相邻的位置,一共搬运d天,问你1号位置最多能有多少东西
题解:肯定是贪心往1号位置搬,先从2号位置搬,再从3号位置搬,一直搬到到达第d天或者全部搬完为止
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int n, m, a[N]; void solve() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++) { int num = min(a[i],m/i); a[0]+=num; m-=num*i; } printf("%d\n",a[0]); } int main() { int t; for (scanf("%d", &t); t >= 1; t--) solve(); }
B.
题意:一个人要从(0,0)走到(x,0),但是每次只能走他喜欢的步数,他有n个喜欢的步长,你每次可以选择其中的一种,问你他走到(x,0)最少需要几步。
题解:分析可以发现除了x恰好等于其中一个喜欢的步数答案为1以外,其他都可以通过选择最大的步长走到,并且答案是最优的,如果x%最长的步数恰好为0那么就一直直走;否则前面直走,走到小于2倍步长斜着走即可。
就是对x向上取整
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int n, x, a[N]; map<int,int>H; void solve() { H.clear(); scanf("%d%d",&n,&x); for(int i=0;i<n;i++) { scanf("%d",&a[i]); H[a[i]]=1; } sort(a,a+n); if(H[x]) puts("1"); else printf("%d\n",max(2,(x+a[n-1]-1)/a[n-1])); } int main() { int t; for (scanf("%d", &t); t >= 1; t--) solve(); }
C.
题意:给你一个s序列,定义序列t,t满足为s的子序列,并且t的每一位下标在s中构成等差序列。询问在所有的t中,哪种序列出现次数最多。
题解:发现每增加一位都会增加一些限制,这样序列个数肯定不会多,所以我要考虑限制最少的。限制最少的肯定是仅由1个或2个字符组成的,没有任何限制,我们就找这两种就好了。单个的序列我们在遍历的时候更新即可,两个组成的序列,我们在遍历的时候用dp[i][j]记录,表示以i为开头,以字符j结尾的序列次数
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 5; ll a[30], dp[30][30]; int main() { string s; cin >> s; ll ans = 0; for (int i = 0; i < s.length(); i++) { for (int j = 0; j < 26; j++) { dp[j][s[i] - 'a'] += a[j]; ans = max(ans, dp[j][s[i] - 'a']); } a[s[i] - 'a']++; ans = max(ans, a[s[i] - 'a']); } printf("%lld\n", ans); return 0; }
D.
题意:一共有n个点和m条边,有k个特殊点,要求从中选取两个建一条边使得从1到n的最短路最大
题解:设ax为1号点到k个节点中的一个节点x的最短路径,by为n号节点到k个节点中的另一个节点y的最短路径,1号节点通过x、y路径到n的距离为ax+by+1。那么交换x、y以后,距离为ay+bx+1,要求最短路,如果是答案那么只会是min(ax+by+1,ay+bx+1),我们令ax+by+1<ay+bx+1,消掉1,交换ay和by得,ax-ay<bx-by,由此我们可以对(ax-ay)进行排序,对于每一个ax之后的每一个by都是满足ax+by<ay+bx,即为可能的答案,算出其中的最大值与不加边的最短路比较取小着即可。
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; typedef pair<int, int> pii; int a[maxn], dis[2][maxn]; vector<int> G[maxn]; void bfs(int st, int idx) { dis[idx][st] = 0; queue<int> q; q.push(st); while (!q.empty()) { int u = q.front(); q.pop(); for (auto v : G[u]) if (dis[idx][v] == INF) { dis[idx][v] = dis[idx][u] + 1; q.push(v); } } } int main() { memset(dis, INF, sizeof(dis)); int n, m, k; cin >> n >> m >> k; for (int i = 0; i < k; i++) scanf("%d", &a[i]); sort(a, a + k); for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } bfs(1, 0); bfs(n, 1); vector<pii> v; for (int i = 0; i < k; i++) v.emplace_back(dis[0][a[i]] - dis[1][a[i]], a[i]); sort(v.begin(), v.end()); int ans = 0, tmp = 0; for (int i = 0; i < v.size(); i++) { if (i) ans = max(ans, tmp + dis[1][v[i].second] + 1); tmp = max(tmp, dis[0][v[i].second]); } cout << min(dis[0][n], ans) << endl; return 0; }