A. Cow and Haybales
分析
水题直接代码。。
代码
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false);
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
int ar[mxn];
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
int n, d;
scanf("%d %d", &n, &d);
for(int i = 0; i < n; i ++)
scanf("%d", &ar[i]);
int ct = ar[0];
for(int i = 1; i < n && d > 0; i ++)
{
int t = (d / i);
int c = min(t, ar[i]);
ct += c;
d -= c * i;
}
printf("%d\n", ct);
}
return 0;
}
B. Cow and Friend
分析
- 题意
- 给我我们n个兔子喜欢的数字,每次兔子🐰可以沿着任意的方向跳一段距离,这个距离为兔子喜欢的数字,现在兔子想从(0,0)到(s,0)问兔子最少需要跳多少次??
- 思路
- 每次兔子都以最大距离沿着x轴方向跳,如果最大跳跃距离正好是s的倍数的话直接跳就行了,否则跳到最后,剩下的最后一段距离小于当前兔子的最大跳跃距离的话,我们要对这个情况进行分类讨论,设之前兔子已经跳了t步,如果t>=1那么可以让兔子之前的t步稍微条约的时候有点向上的倾斜角度,给最后一段腾出一段距离,是最后一次恰好可以跳到终点,这个时候答案就是t+1,如果t = 0的话,我们至少需要两步来跳一个等腰三角形,从而到达目的地,此时答案为 2
代码1
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false)
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
int ar[mxn];
int main()
{
/* fre(); */
int t;
scanf("%d", &t);
while(t --)
{
int n, s;
scanf("%d %d", &n, &s);
int mx= 0;
int ans = 0;
for(int i = 1; i <= n; i ++)
{
scanf("%d", &ar[i]);
mx = max(mx, ar[i]);
if(ar[i] == s)
ans = 1;
}
if(ans)
{
printf("%d\n", ans);
continue;
}
if(s % mx == 0)
{
ans = s / mx;
}
else
{
ans = s / mx + 1;
}
printf("%d\n", max(2, ans));
}
return 0;
}
代码2
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false);
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
int ar[mxn];
map<int,int> mp;
int main()
{
/* fre(); */
int T;
scanf("%d", &T);
while(T --)
{
mp.clear();
int n, d;
scanf("%d %d", &n, &d);
for(int i = 1; i <= n; i ++)
scanf("%d", &ar[i]), mp[ar[i]] ++;
int ans = INF;
for(int i = 1; i <= n; i ++)
{
int mx = ar[i];
int D = d;
int t = D / mx;
D -= t * mx;
if(D)
{
if(mp[D])
t += 1;
else
{
if(t >= 1)
t += 1;
else
t += 2;
}
}
/* printf("%d = %d %d\n", i, t, D); */
ans = min(ans, t);
}
printf("%d\n", ans);
}
return 0;
}
C. Cow and Message
分析
- 题意
注意在👇我们说的“等差子序列”都是指的是在长度相同的情况下,某个相同子序列(并不是指的所有长度相同的子序列)
- 给我们一个长度为n的字符串s,问s的所有成等差序列的子序列中,出现次数最多的那个等差子序列出现的次数是多少次?
- 思路
- 首先明白在s的所有子串中,我们只需要讨论 长度为1的子序列、长度为2的子这两种情况(而且这两种情况的子序列本身有长度的关系已经是成等差序列了),对于长度大于2的成等差序列的子串我们都可以是为是在长度2的等差子序列的基础上加上另外一个字符形成的的,所以长度大于2的等差子序列出现的次数一定小于等于长度为2的等差子序列的长度为
- 为什么还要单独讨论长度为1的等差子序列呢?仅仅讨论长度为2的等差子序列不行吗?,,,,不行,因为长度为1的子序列可能比长度为2的子序列出现的次数还多(如 lol)
代码
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false)
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
ll dp1[mxn]; //统计单个字符出现的次数
ll dp2[30][30]; //统计仅有2个字符组成的子串的数量
int main()
{
ios;
/* fre(); */
string s;
cin >> s;
for(int i = 0; i < s.size(); i ++)
{
int ch = s[i] - 'a';
for(int j = 0; j < 26; j ++)
{
dp2[j][ch] += dp1[j];
}
dp1[ch] ++;
}
ll ans = 0;
for(int i = 0; i < 26; i ++) ans = max(ans, dp1[i]);
for(int i = 0; i < 26; i ++)
for(int j = 0; j < 26; j ++)
ans = max(ans, dp2[i][j]);
printf("%lld\n", ans);
return 0;
}
D. Cow and Fields(两遍spfa+枚举两个特殊点建立边)
分析
- 题意
- 给我们一个n个点,m条边的无向图,先给我们k个点,让我们在这个k个点之间选择一对进行 建一条边,问过建立了这条边,我们能够使从1到n的最短路距离的最大值可变为多少(我们建立的这条边,可能是最短路距离减小,
而我们要做的就是合理的建边,使最短路距离尽可能的减少,这样最短路距离就尽可能的大了
)?
- 思路
- 跑两遍 spfa,第一计算起点1到其他点x到距离dis1[x];第二遍计算n到其他点y的距离dis2[y]
- 接下的核心思想就是枚举k中的任意两个点x,y,这时从1到n经过x,y两点有两条路可以走,第一条:1-x-y-n,第二条:1-y-x-n,我们选择两条路线距离较小的那么个距离 d = m i n ( d i s 1 [ x ] + 1 + d i s 2 [ y ] , d i s 1 [ y ] + 1 + d i s 2 [ x ] ) d =min(dis1[x]+1+dis2[y],~~dis1[y]+1+dis2[x]) d=min(dis1[x]+1+dis2[y], dis1[y]+1+dis2[x]),这样由于我们枚举的x,y的值不同,那么得到的d的值也不同,在所有的d的取值中我们取最大的那个d, 之后题目的答案就是 m i n ( d , d i s 1 [ n ] ) min(d,dis1[n]) min(d,dis1[n])
- 注意 3. 说的是核心思想是没问题的,但是我不可能暴力枚举x、y的值的(n<2e5),所以要要优化这个暴力枚举的过程,把不可能产生答案的枚举删除掉就行了,而优化的思想是:要想使最短路距离尽可能的大,我们要建立边的两个节点x、y之间的距离应该应该包含尽量少的边,这样我们人为建立的边替代的边就替代边数少了,这样最短路径就可能更长了,,,具体实现看代码
另外一种优化的枚举x、y过程的思路,传送门
优化1代码
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false)
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
vector<int> V;
vector<int> edge[mxn];
int q[mxn * 10];
int dis1[mxn], dis2[mxn]; //dis1 表示从起点1到其他各点的最短路,dis2表示从n到其他的点的最短路
void bfs(int dis[], int s)
{
int qh = 0, qt = 0;
fill(dis, dis + mxn, INF);
q[++ qt] = s;
dis[s] = 0;
while(qt > qh)
{
s = q[++ qh];
for(auto x : edge[s])
{
if(dis[x] == INF)
{
dis[x] = dis[s] + 1;
q[++ qt] = x;
}
}
}
}
int main()
{
/* fre(); */
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
int p;
for(int i = 0; i < k; i ++)
scanf("%d", &p), V.push_back(p);
int u, v;
for(int i = 0; i < m; i ++)
{
scanf("%d %d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
bfs(dis1, 1);
bfs(dis2, n);
vector<pair<int, int> > vec;
for(auto x : V)
vec.push_back(make_pair( dis1[x], x ));
sort(vec.begin(), vec.end());
int ans = 0;
for(int i = 1; i < vec.size(); i ++)
{
int d = dis1[n];
int u = vec[i - 1].second, v = vec[i].second;
d = min(d, dis1[u] + dis2[v] + 1);
d = min(d, dis1[v] + dis2[u] + 1);
ans = max(ans, d);
}
printf("%d\n", ans);
return 0;
}
优化2代码
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
#define ios ios::sync_with_stdio(false)
#define endl '\n'
#define PI acos(-1)
#define PB push_back
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define mod 998244353
#define lowbit(abcd) (abcd & (-abcd))
const int mxn = 2e5 + 10;
vector<int> V;
vector<int> edge[mxn];
int q[mxn * 10];
int dis1[mxn], dis2[mxn]; //dis1 表示从起点1到其他各点的最短路,dis2表示从n到其他的点的最短路
void bfs(int dis[], int s)
{
int qh = 0, qt = 0;
fill(dis, dis + mxn, INF);
q[++ qt] = s;
dis[s] = 0;
while(qt > qh)
{
s = q[++ qh];
for(auto x : edge[s])
{
if(dis[x] == INF)
{
dis[x] = dis[s] + 1;
q[++ qt] = x;
}
}
}
}
int main()
{
/* fre(); */
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
int p;
for(int i = 0; i < k; i ++)
scanf("%d", &p), V.push_back(p);
int u, v;
for(int i = 0; i < m; i ++)
{
scanf("%d %d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
bfs(dis1, 1);
bfs(dis2, n);
vector<pair<int, int> > vec;
for(auto x : V)
vec.push_back(make_pair( dis1[x] - dis2[x], x ));
sort(vec.begin(), vec.end());
int mx = -INF, bs = 0;
for(auto x : vec)
{
bs = max(bs, dis2[x.second] + mx);
mx = max(mx, dis1[x.second]);
}
printf("%d\n", min(dis1[n], bs + 1));
return 0;
}