蒟蒻暑假集训第九篇博客
2021年上海市赛
A.小 A 的点面论
题意:题目就是给你两个向量,让你求一个和这两个向量垂直的向量,所求的向量的x,y,z的范围都是-200≤x,y,z≤200
。
思路:暴力枚举就行了,时间复杂度是8e6;
代码:
#include <bits/stdc++.h>
using namespace std;
int x1, y1, z1, x2, y2, z2;
int main()
{
cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
for(int i = -200; i <= 200; i ++ )
{
for(int j = -200; j <= 200; j ++ )
{
for(int z = -200; z <= 200; z ++ )
{
if(i * x1 + j * y1 + z * z1 == 0 && i * x2 + j * y2 + z * z2 == 0 && (i != 0 || j != 0 || z != 0))
{
cout << i << " " << j << " " << z << endl;
return 0;
}
}
}
}
}
C. 小 A 的期末考试
题意:给你一个n,和k,n表示小A全班的总人数,k表示小A的学号,下面的n行给你小A班上的同学的学号和分数。小A能进行以下操作:
(1)如果小A的分数比60低,小A把她的分数改成60
(2)如果小A的班上同学的分数比他们班平均分(按照所有人一开始的分数算平均分)高,那么小A可以把该同学的分数-2,但是要保证大于零,结果按照学号的分数输出同学的分数。
思路:本题是纯粹的模拟。但是有几个地方要注意下:(这两个点是易错点)
(1)求平均数的时候要强制类型转换下aver = (double) sum / n or aver = sum * 1.0 / n
(2) 题目中给的学号不是按照顺序给的,所以判段这个人是不是小A,要用a[i].index
来判断,不能用i。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, k;
struct student
{
int s, index;
}a[110];
bool cmp (student A, student B)
{
return A.index < B.index;
}
int main()
{
cin >> n >> k;
int sum = 0;
for(int i = 1; i <= n; i ++ )
{
cin >> a[i].index;
cin >> a[i].s;
sum += a[i].s;
if(a[i].index == k)
{
if(a[i].s < 60) a[i].s = 60;
}
}
double aver = (double)sum / n;
for(int i = 1; i <= n; i ++ )
{
if(a[i].index != k && a[i].s >= aver)
{
a[i].s -= 2;
if(a[i].s < 0) a[i].s = 0;
}
}
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i ++ ) cout << a[i].s << " ";
cout << endl;
return 0;
}
E. Zztrans 的庄园
题意:给你A、B、C、D、S五种鱼,对应的卖价依次是80、54、24、10000,然后告诉你每次钓鱼的成本是23元;然后给你一个n,表示池塘里有多少鱼,给你一个k,表示钓鱼次数,问你钓鱼的收益期望。
思路: 先求出每种鱼出现的总概率分别乘以他们的价格再相加,最后减去钓鱼的总成本。
代码:
#include <bits/stdc++.h>
using namespace std;
int n;
double k;
double d, a, b, c, s;
double ans;
int main()
{
// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n >> k;
for(int i = 1;i <= n; i ++ )
{
char x;
double y;
cin >> x >> y;
if(x == 'D') d += y;
if(x == 'A') a += y;
if(x == 'B') b += y;
if(x == 'C') c += y;
if(x == 'S') s += y;
}
ans = (double)((d * 16 + c * 24 + b * 54 + a * 80 + s * 10000) * k - 23 * k);
cout << ans << endl;
return 0;
}
G、鸡哥的雕像
题意:给你一个n,和n个数,输出除了第i个数以外的其他的数的乘积。
思路:本题采用前缀积和后缀积,求到第i个数的时候,就把它前面的所有的数相乘再乘上后面的所有的数。
注意:求前缀积和后缀积的时候要不断的取mod。
另外为什么把所有的数全部乘起来再分别除以第i个数不对,因为所有的数相乘由于数字过大难以存储,所以要取模,但是取模后再做乘法会出现错误,例如:10 / 5 = 2 but(10 % 3 ) / 5 就不能于 2 了。
代码:
#include <bits/stdc++.h>
using namespace std;
int n;
int a[100010];
long long qian[100010];
long long hou[100010];
const int mod = 998244353;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++ ) cin >> a[i];
qian[1] = a[1], hou[n] = a[n];
for(int i = 2; i <= n; i ++ ) qian[i] = a[i] * qian[i - 1] % mod;
for(int i = n - 1; i >= 1; i -- ) hou[i] = a[i] * hou[i + 1] % mod;
for(int i = 1; i <= n; i ++ ){
if(i - 1 >= 1 && i + 1 <= n) cout << qian[i - 1] * hou[i + 1] % mod << " ";
else if( i - 1 == 0) cout << hou[i + 1] << " ";
else if( i + 1 == n + 1) cout << qian[i - 1] << " ";
}
return 0;
}
J. Alice and Bob-1
题意:给你n个数,有正有负,然Alice 和 Bob 不断去选择里面的数,Alice选的数的绝对值称为 A,Bob选择的数的绝对值成为B,然后Alice 想要A - B最大,Bob想让A - B 最小,Alice 先选, 问你他们都以最优的方案选,问你最后A - B的值为多少。
思路:Alice从最大的开始选,Bob选第二大的,这么选满足题意。
Alice从最小的负数开始选,Bob从第二小的负数开始选,这样也满足题意。
答案就是这两个取最大值(因为Alice先选的)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
vector<int> a;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n;
LL sum = 0;
for(int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
sum += x;
a.push_back(x);
}
sort(a.begin(),a.end());
LL suma = 0, sumb = 0;
for(int i = 0; i < n; i += 2 ) suma += a[i];
sumb = sum - suma;
LL ans = abs(suma) - abs(sumb);
suma = 0, sumb = 0;
for(int i = n - 1; i >= 0; i -= 2) suma += a[i];
sumb = sum - suma;
cout << max(ans, abs(suma) - abs(sumb)) << endl;
return 0;
}