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,我們選擇兩條路線距離較小的那麼個距離 ,這樣由於我們枚舉的x,y的值不同,那麼得到的d的值也不同,在所有的d的取值中我們取最大的那個d, 之後題目的答案就是
- 注意 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;
}