電子科技第十屆ACM趣味程式設計競賽第三場(正式賽)官方題解
阿新 • • 發佈:2019-02-13
A 秦皇炒飯
source: Pxt
偶數不滿足兩兩互質,因此最少要分n/2組。相鄰的兩個數2k與2k+1一定互質可以分為1組,編號為1的可以加入任意組。
因此,.
#include<cstdio>
using namespace std;
int i,n;
int main()
{
scanf("%d",&n);
if(n>1) n/=2;
for(i=1;i<=n;++i) printf("Wed.Strong");
return 0;
}
B 摩天樂
source: Range
對於輸入在同一層的特判。如果一開始就在電梯範圍,就直接到同一行再走。否則分左邊下去和右邊下去的情況,可以知道肯定是從
該題測試組數T最大值實際上為1000,這是我們的過失,在這裡向開陣列存資料導致RE的同學道個歉了。
#include <iostream> #include <stdio.h> #include <algorithm> #include <math.h> using namespace std; long long n, m, l, r, a, b, c, d; int main() { int T; cin >> T; while (T--) { cin >> n >> m >> l >> r >> a >> b >> c >> d; if (a == c) { cout << abs(b-d) << endl; continue; } long long ans = 0; if (b <= l || b >= r) { ans = abs(a-c) + abs(b-d); } else { long long cost1 = b-l+abs(d-l)+abs(a-c); long long cost2 = r-b+abs(r-d)+abs(a-c); ans = min(cost1, cost2); } cout << ans << endl; } return 0; }
C Akane
source: meltout
記錄%m餘0,1,2,....m-1的元素個數
重排列後儘量使餘數和為m的元素相鄰,假設兩者個數分別為a,b,若a=b,則最多隻能構成a2-1對,否則,可以通過將個數更多的元素放在外圍,構造min(a,b)2對
特別地,%m餘0的元素可以不計順序直接放在一起,假設元素個數為a,可構成a-1對
若m為偶數,則%m餘m/2的元素也可以直接放在一起,對答案貢獻同上
需要注意a=0時特判,以免對答案做負貢獻
#include <cstdio> #include <algorithm> using namespace std; const int maxN=1e6+5; int a[maxN]; int main() { int k,n,m,x; scanf("%d%d",&n,&m); for(k=0;k<n;k++) { scanf("%d",&x); a[x%m]++; } int ans=max(0,a[0]-1); for(k=1;k<(m+1)/2;k++) { ans+=min(a[k],a[m-k])*2; if(a[k]==a[m-k] && a[k]!=0)ans--; } if(m%2==0)ans+=max(0,a[m/2]-1); printf("%d",ans); return 0; }
D 強哥打電話
source: zhsq11, forgottencsc
注意到情侶隊友打電話的時間是順序給出的,所以順序檢查即可。
題目要求情侶隊友的電話時間是左閉右開的,也就是說掛下電話的一瞬間是可以打通電話的。
因此暴力檢查一下每段強哥打電話的區間能不能打通就行了。
關於這個時間表示法的處理辦法:可以寫一個將給出的時間轉換成秒數的函式,這樣就比較好進行處理了。
#include <cstdio>
#include <iostream>
using namespace std;
const int Time_Max = 24 * 60 * 60;
const int MAXN = 100 + 10;
int From[MAXN], To[MAXN]; int N;
int Qiang_Time, Qiang_Interval, Qiang_Wait;
int Time_Conversion()
{
int hour, min, sec;
scanf("%d:%d:%d", &hour, &min, &sec);
return hour * 60 * 60 + min * 60 + sec;
}
void output(int seconds)
{
int hour = seconds / (60 * 60);
int min = (seconds - hour * (60 * 60)) / 60;
int sec = seconds - hour * (60 * 60) - min * 60;
if(seconds >= Time_Max)
printf("-1\n");
else
printf("%02d:%02d:%02d\n", hour, min, sec);
exit(0);
}
void read()
{
cin >> N;
int h1, m1, s1, h2, m2, s2;
for(int i = 0;i < N; ++i)
{
From[i] = Time_Conversion();
To[i] = Time_Conversion();
}
Qiang_Time = Time_Conversion();
Qiang_Interval = Time_Conversion();
Qiang_Wait = Time_Conversion();
return;
}
void find()
{
for(int i = 0;i < N; ++i)
{
while(Qiang_Time <= To[i])
{
if(Qiang_Time < From[i])
output(Qiang_Time);
if(Qiang_Time + Qiang_Wait >= To[i])
output(To[i]);
Qiang_Time += Qiang_Interval;
}
}
output(Qiang_Time);
return;
}
int main()
{
read(); find();
return 0;
}
E 暴擊貓
source: moe
用表示第j次攻擊前有i 層buff的概率,在無限次攻擊後i將會無意義,也就是說會收斂。所以用表示無限次數攻擊後有i層buff的概率。顯然為p,為p*(1-p),以此類推, 。注意因為有buff層數上限所以,解得 。剩下的就是算期望再作比了。
另解,直接暴力模擬,用隨機函式來隨機是否暴擊然後模擬過程,算出兩種總傷害然後作比。
#include <bits/stdc++.h>
using namespace std;
int main()
{
double p, k, a;
int n;
scanf("%lf%lf%lf%d", &p, &k, &a, &n);
double init = p * k + (1 - p) * 100;
double res = 0, base = p;
for (int i = 1; i <= n; i++)
{
res += base * (k + a * (i - 1)) * p;
base = base * (1 - p);
}
res += base * (k + n * a);
res += (1 - p) * 100;
printf("%.3lf", res / init);
return 0;
}