题解
第一题
令单次砸出第i个式神概率为
P
i
(
0
≤
P
i
≤
1
)
P_i (0 \leq P_i \leq 1)
Pi(0≤Pi≤1), 则有
两次以内砸出的概率为
P
i
=
P
+
(
1
−
P
)
∗
P
P_i = P + (1 - P) * P
Pi=P+(1−P)∗P
于是有第i个式神砸出的期望为
P
i
P_i
Pi
由于砸不同式神的事件之间互相独立,所以总期望简单地将式神相加即可。
#include <bits/stdc++.h>
using namespace std;
double ans, in; int N;
int main()
{
cin >> N;
for(int i = 0;i < N; ++i)
{
scanf("%lf", &in);
in /= 100;
in = (1 - in) * in + in;
ans += in;
}
printf("%.3lf\n", ans);
return 0;
}
第二题
多边形合法的条件是:最长边小于其他边之和。
换句话说,边长之和应该大于最长边的二倍。
于是记录一下当前最长的边和边长之和即可。
#include <bits/stdc++.h>
using namespace std;
int N;
long long now, sum;
long long maxnow;
int main()
{
cin >> N;
for(int i = 0;i < N; ++i)
{
scanf("%lld", &now);
sum += now;
if(now > maxnow)
maxnow = now;
if(sum > 2 * maxnow)
{
printf("%d\n", i + 1);
return 0;
}
}
printf("-1\n");
return 0;
}
第三题
暴力就好了。因为一次只能使得某个字母的次数减一,所以每个字母至少都被拿了它存在的次数那么多次。于是我们从需要拿的次数最多的开始拿,一直拿到全部拿完为止。
#include <bits/stdc++.h>
using namespace std;
int N;int num[30];int ans;
void find(int pl, int here) // 从最高点开始向两侧拿
{
int now = here;
for(int i = pl;i >= 0; --i)
{
now = min(now, num[i]);
num[i] -= now;
}
now = here;
for(int i = pl + 1;i < 26; ++i)
{
now = min(now, num[i]);
num[i] -= now;
}
return;
}
void solve()
{
while(true)
{
int pl = -1, maxnum = -1;
for(int i = 0;i < 26; ++i)
{
if(num[i] > maxnum)
{
maxnum = num[i];
pl = i;
}
}
if(maxnum == 0) // 拿完了就结束了
break;
else
{
ans += maxnum;
find(pl, maxnum);
}
}
cout << ans << endl;
return;
}
int main()
{
cin >> N; string str; cin >> str;
for(int i = 0;i < str.length(); ++i)
++num[str[i] - 'a'];
solve();
return 0;
}
第四题
模拟题。
就照着题意模拟就好了。要求有点多。但是思路应该挺清楚的。
#include <bits/stdc++.h>
using namespace std;
int N, K;
int num[10];
int main()
{
cin >> N >> K;
for(int i = 1;i <= N; ++i)
{
string str;cin >> str;
++num['F' - 'A'];
if(num['F' - 'A'] == 50)
{
if(K >= i) printf("%d F\n", i);
else printf("Feizhou Yin\n");
return 0;
}
int len = str.length();
for(int j = 0;j < len; ++j)
{
++num[str[j] - 'A'];
if(num[str[j] - 'A'] == 50)
{
if(K >= i) printf("%d %c\n", i, str[j]);
else printf("Feizhou Yin\n");
return 0;
}
}
}
if(N < K) printf("AMNZ");
else printf("Feizhou Yin\n");
return 0;
}
第五题
可证:一个数随机打乱后形成的新数,与原数之差的绝对值必然是9的整数倍。
证明:
令初始数字为
X
n
X
n
−
1
.
.
.
X
0
X_nX_{n-1}...X_0
XnXn−1...X0
现在我们交换其中两个数位,
X
a
X_a
Xa 和
X
b
X_b
Xb
则两数之差为
(
X
a
∗
1
0
a
+
X
b
∗
1
0
b
)
−
(
X
b
∗
1
0
a
+
X
a
∗
1
0
b
)
(X_a * 10^a + X_b * 10^b) - (X_b * 10^a + X_a * 10^b)
(Xa∗10a+Xb∗10b)−(Xb∗10a+Xa∗10b)
=
(
X
a
−
X
b
)
∗
1
0
a
+
(
X
b
−
X
a
)
∗
1
0
b
= (X_a - X_b) * 10^a + (X_b - X_a) * 10^b
=(Xa−Xb)∗10a+(Xb−Xa)∗10b
=
(
X
a
−
X
b
)
∗
(
1
0
a
−
1
0
b
)
= (X_a - X_b) * (10^a - 10^b)
=(Xa−Xb)∗(10a−10b)
=
(
X
a
−
X
b
)
∗
(
1
0
(
a
−
b
)
−
1
)
∗
1
0
b
= (X_a - X_b) * (10^{(a - b)} - 1) * 10^b
=(Xa−Xb)∗(10(a−b)−1)∗10b
令(a > b),则
(
1
0
(
a
−
b
)
−
1
)
=
999...9
(10^{(a - b)} - 1) = 999...9
(10(a−b)−1)=999...9 (共
a
−
b
a - b
a−b 个9),是9的整数倍(
9
∗
111...1
9 * 111...1
9∗111...1)。
于是互换两个数位后得到的数与原数的差值必然是9的整数倍。
任意互换数位后的数,必然可由有限次两个数位互换得到。
于是前述命题得证。
于是问题转化为如何用当前的数字任意排列,得到最小的数。
显然,较大的数位上的数字应该尽可能小。于是对数位上的数字进行排序,小的在前大的在后即可。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000 + 10;
char ss[MAXN];
int main()
{
scanf("%s", ss);
int len = strlen(ss);
sort(ss, ss + len);
printf("%s", ss);
return 0;
}