A.Archmage
題意
大法師有n點初始魔法,每秒可以召喚一個水元素,消耗x點魔法(現有魔法不足則不能召喚),無論是否召喚,這一秒結束的時候會回覆y點魔法,問m秒可以召喚多少水元素。
思路
比賽的時候想着找循環節然後開頭和結尾模擬一下,但是瘋狂wa。賽後補題了解到可以直接套公式。分兩類情況討論:x<=y則每秒都可以召喚水元素,即可召喚m個;x>y時,m秒的總魔法值爲n+(m-1)*y(因爲最後一秒回覆的魔法值是在召喚後所以用不到,故m-1),召喚一個水元素消耗x點魔法,故召喚水元素爲(n+(m-1)*y)/x。綜合可得,ans=min(m,(n+(m-1)*y)/x).
AC代碼
#include <iostream>
using namespace std;
int main()
{
int t;
long long x,y,n,m;
cin >> t;
while(t--)
{
cin>>n>>m>>x>>y;
cout << min(m,(n+(m-1)*y)/x) << endl;
}
return 0;
}
B. Bamboo Leaf Rhapsody(簽到題)
題意
給幾組三維座標,求到原點的最短距離,保留三位小數。
AC代碼
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,x,y,z;
int ans=1e8;
scanf("%d",&n);
while(n--)
{
scanf("%d %d %d",&x,&y,&z);
ans=min(ans,x*x+y*y+z*z);
}
printf("%.3lf",sqrt(ans*1.0));
return 0;
}
C. Cheat Sheet
題意
給出m個單詞,選取其中的部分或者全部放入n個格子裏,每個單詞之間空至少一格,要求放入格子中的單詞不重複且數量最多。
思路
逐個輸入字符 循環遍歷已有單詞判斷是否重複,不重複則填入字符串數組,然後按照字符長度排序,優先輸出短的。
AC代碼
#include <bits/stdc++.h>
#include<algorithm>
using namespace std;
bool cmp(pair<string,int> p1,pair<string,int> p2)
{
return p1.second < p2.second;
}
int main()
{
int m,n;
cin >> n >> m;
string str;
vector<pair<string,int> > vc;
for(int i = 0; i < m ; i++)
{
cin >> str;
int flag=0;
for(int i=0;i<vc.size();i++)
{
if(vc[i].first==str)
{flag=1;break;}
}
if(flag!=1)
vc.push_back(make_pair(str,str.size()));
}
sort(vc.begin(),vc.end(),cmp);
int ans=0;
for(int i = 0; i < vc.size(); i++)
{
n=n-vc[i].second;
if(n>=0)
{
ans++;
n--;
// cout << vc[i].first << endl;
}
else break;
}
printf("%d\n",ans);
return 0;
}
H. Hay Mower
題意
有一塊n*m的草坪,每秒i行j列的草會生長aij那麼多,有k次操作,每次操作會在t秒的時候將第x(y)行(列)的草割完,問所有操作後總割草數,數據過大取模998244353。
思路
無論什麼時候割草,其實只要考慮最後一次割草的時間即可,所以可以用一個dp數組記錄每個格子最後割草的時間×生長速度,遍歷所有格子累加就是總割草數了,需要注意的是多個地方的取模,不然數據量過大會溢出,在代碼裏有體現。
AC代碼
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
long long dp[510][510];
long long mp[510][510];
int main()
{
int n,m,k;
cin >> n >> m >> k;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin >>mp[i][j];
while(k--)
{
char c;
long long x,t;
cin >> c >> x >> t;
if(c=='r')
{
for(int i=1; i<=m; i++)
{
if(dp[x][i]<t)
dp[x][i]=t;
}
}
else
{
for(int i=1; i<=n; i++)
{
if(dp[i][x]<t)
dp[i][x]=t;
}
}
}
long long ans=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
ans+=(dp[i][j]%998244353)*(mp[i][j]%998244353);
ans=ans%998244353;
}
}
printf("%lld",ans);
return 0;
}
L. Lottery Tickets
題意
給出若干個0-9的數字隨意組合,求最大的能被4整除的整數。
思路
可以知道只要個位和十位數字組成的兩位數能被4整除那麼整個數字能被整除(因爲從三位數開始整百整千整萬隻要是整的都能被4整除,那麼加上一個能被4整除的兩位數則整個數也能被整除),所以只要組出最小的兩位數然後把剩餘的數按照高位大數字低位小數字的原則分配即可,要注意前置0,單獨一個0、4、8等情況的特判,這種做法特判太多很容易出錯,我按照這種思路越改越亂,最後用了朋友的暴力求解方法,下面是他(@ZXR)的代碼
AC代碼
#include <bits/stdc++.h>
using namespace std;
const int N = 9e5 + 10;
stack<int> s;
char str[N];
int c[25], cnt;
bool get_2() {
int a = 20, b = 20;
for (int i = 0; i < 10; i++) {
if (!c[i]) continue;
c[i]--;
for (int j = 0; j < 10; j++) {
if (!c[j]) continue;
if ((i * 10 + j) % 4) continue;
if (max(i, j) < max(a, b)) {
a = i, b = j;
} else if (max(i, j) == max(a, b)) {
if (min(i, j) < min(a, b)) {
a = i, b = j;
} else if (min(i, j) == min(a, b) &&
(i * 10 + j) > (a * 10 + b)) {
a = i, b = j;
}
}
}
c[i]++;
}
if (a == 20 && b == 20) return false;
s.push(b);
s.push(a);
c[a]--;
c[b]--;
return true;
}
void num2str() {
cnt = 0;
for (int i = 9; i >= 0; i--) {
while (c[i]--) {
str[cnt++] = i + '0';
}
}
str[cnt++] = s.top() + '0';
s.pop();
str[cnt++] = s.top() + '0';
s.pop();
str[cnt] = 0;
}
int main() {
int t, num;
scanf("%d", &t);
while (t--) {
num = 0;
bool f = false;
memset(c, 0, sizeof(c));
for (int i = 0; i < 10; i++) {
scanf("%d", &c[i]);
num += c[i];
if (c[i] && i) f = true;
}
if (!f) {
printf("0\n");
} else if (num == 1) {
for (int i = 0; i < 10; i++) {
if (c[i] == 1) {
if (i % 4)
printf("-1\n");
else {
printf("%d\n", i);
}
break;
}
}
} else {
if (!get_2()) {
bool flag = false;
for (int i = 8; i >= 0; i -= 4) {
if (c[i]) {
printf("%d\n", i);
flag = true;
break;
}
}
if (!flag) printf("-1\n");
} else {
num2str();
printf("%s\n", str);
}
}
}
return 0;
}
總結
這次比賽被大法師卡了好久好久,最後也沒A出來,時間不夠只A出了兩道,好菜好菜,思維還是得多鍛鍊,對題目不夠敏感,還是得多刷題,爲了自己的初心,不負努力,繼續加油吧。