首先感谢大家参加我们学校的新生赛!希望大家都玩的开心!
在此也对 题的失误致歉~(
题经后续检查,确定没有问题)
那么接下来是题解部分~
A 逐梦季
按要求随便输出即可。
#include <iostream>
using namespace std;
int main() {
// 填入任意非空白内容(此处以"Programming!"为例)
cout << "I Love ACM and Programming!" << endl;
return 0;
}
B 美味的酱油
使用min函数/if结构判断均可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
int n;
cin>>n;
cout<<min(n*5,100ll);
return 0;
}
C 我的父亲是瓦匠
注意使用 ,
会被卡精度。
#include <cstdio>
using namespace std;
int main() {
double l, m;
scanf("%lf %lf", &l, &m);
double area = l * m;
printf("%.10f\n", area);
return 0;
}
D 求和
注意使用 ,
会被卡。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll N = 1e6 + 10;
ll a[N],b[N];
void solve() {
int n;
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++) cin >> b[i];
for(int i=1;i<=n;i++)
cout << (a[i]+b[i]) << " ";
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll _ = 1;
// cin >> _;
while (_--) solve();
return 0;
}
E 第五
小模拟,数组a用于计算编号为x的选手的积分,数组vis用来标记编号为x的选手是否淘汰,sum为剩余人数,初始值为6。
当时
,当
时
后标记
,同时
。最后跑一个
从
到
的循环将
即未淘汰的选手的积分加上
,并不断取当前积分最大值求出冠军编号
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void solve(){
vector<ll> a(7, 0), vis(7, 0);
ll sum = 6;
ll q;
cin >> q;
while(q--) {
ll op, x, y;
cin >> op >> x >> y;
if(vis[x]) continue;
if(op == 1) a[x] += y;
else {
a[x] += y;
vis[x] = 1;
sum--;
}
}
ll ans = 0, mx = 0;
for (ll i = 1; i <= 6; i++) {
if(vis[i] == 0) a[i] += 100 * sum;
if(a[i] > mx) {
mx = a[i];
ans = i;
}
}
cout << ans << '\n';
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll _ = 1;
// cin >> _;
while (_--) solve();
return 0;
}
F 两条线
数学,给出两条直线 ,
,平行的条件为
等于
且
不等于
,重合的条件为
等于
且
等于
,其他情况为有唯一交点。该题即需要注意重合情况
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void solve(){
double k1, b1, k2, b2;
cin >> k1 >> b1 >> k2 >> b2;
if(k1 == k2) {
if(b1 == b2) cout << "Wrong Answer\n";
else cout << "Ping Xing";
return ;
}
double x = 1.0 * (b2 - b1) / (k1 - k2);
double y = k1 * x + b1;
cout << fixed << setprecision(10) << x << " " << y << '\n';
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// init();
// Prime();
cout << fixed << setprecision(6);
ll _ = 1;
// cin >> _;
while (_--) solve();
return 0;
}
G 摩天轮
该题涉及到时间,使用 scanf 能更好输入,根据题意能把22:00:00之前的摩天轮的转速 和之后的转速
求出来,并把输入的时间换算成以秒为单位的一个整数
和
,以及22:00:00对应的整数
,然后分类讨论算出最后角度即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void solve(){
int hh, mm, dd, HH, MM, DD;
scanf("%d:%d:%d %d:%d:%d", &hh, &mm, &dd, &HH, &MM, &DD);
double v1 = 360.0 / (1.0 * 30 * 60);
double v2 = 360.0 / (1.0 * 20 * 60);
int t1 = hh * 3600 + mm * 60 + dd;
int t2 = HH * 3600 + MM * 60 + DD;
int t = 22 * 3600;
double ans;
if(t1 >= t) ans = (t2 - t1) * v2;
else if(t2 <= t) ans = (t2 - t1) * v1;
else ans = (t - t1) * v1 + (t2 - t) * v2;
printf("%.1lf", ans);
}
signed main(){
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll _ = 1;
// cin >> _;
while (_--) solve();
return 0;
}
H 鸡你太美
已知这 个鸡圈的容量都是
的幂次,且互不相同。因此,我们可以将它们看作二进制数的各个位。任意选择一些鸡圈,总容量就是这些鸡圈容量的和。由于每个鸡圈对应一个二进制位(选或不选),所以总容量可以表示
到
之间的任意整数(包括
和
)。
因此,问题转化为:判断 是否在
到
之间(包括两端)。由于题目中
,所以实际上只需判断
是否小于等于
。
#include <bits/stdc++.h>
using namespace std;
int n, k;
int main() {
cin >> n >> k;
// 计算2^k - 1
int max_capacity = (1 << k) - 1;
if (n <= max_capacity)
cout << "YES";
else
cout << "NO";
return 0;
}
I 今天吃什么
一共只有六个输入,将每次输入的食物进行统计次数求出票数最多的即可,因不保证票数完全相等,即可能最后有多个食物输出。
C:
#include<stdio.h>
#include<string.h>
int main(){
char name[6][20];
char food[20];
int sum = 0;
int cnt[6];
for (int i = 1; i <= 6; i++) {
scanf("%s", &food);
bool flag = 0;
for (int j = 0; j < sum; j++) {
if(strcmp(name[j], food) == 0) {
cnt[j]++;
flag = 1;
break;
}
}
if(flag == 0) {
strcpy(name[sum], food);
cnt[sum] = 1;
sum++;
}
}
int mx = 0;
for (int i = 0; i < sum; i++) {
if(cnt[i] > mx) {
mx = cnt[i];
}
}
for (int i = 0; i < sum; i++) {
if(cnt[i] == mx) {
printf("%s\n", name[i]);
}
}
return 0;
}
C++:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void solve(){
map<string, ll> mp;
ll mx = 0;
for (ll i = 1; i <= 6; i++) {
string s;
cin >> s;
mp[s]++;
mx = max(mx, mp[s]);
}
for (auto i : mp) {
if(mx == i.second) cout << i.first << '\n';
}
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
ll _ = 1;
// cin >> _;
while (_--) solve();
return 0;
}
J 是第一个”数学题“吗?
- 考虑直接模拟
次多项式相乘,时间复杂度
- 考虑展开多项式,设多项式为
,因为求每项的系数,等价于
的值,带入原式:
,时间复杂度
。
#include <bits/stdc++.h>
using namespace std;
constexpr int mod = 998244353;
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int n;
cin >> n;
int fac = 1;
for(int i = 3; i <= n+1; i++) {
fac = 1ll*fac*i%mod;
}
cout << fac << '\n';
return 0;
}
K 午枫爱操作
过手模不难发现,对于一段连续的 ,如果这段
右边至少有一个
,那么可以通过一次操作使得这段
都变为
,因为这段
一定是在高位的,所有这样的操作一定是最优的;由于操作后会出现新的
,那么重复之前的过程,直到最后无法操作为止。
所以每次选取左端点为最左边的 ,右端点的距离左端点最近的
,这样可以将这个区间除最后一位其他所有位都变成
,同时提供了下一个区间的左端点,这样反复操作后,一定可以变成形如
的二进制数。
确定了上述方法,可以用模拟来实现,也可以记录最后一个 的位置直接输出。
时间复杂度
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;cin>>n;
string s;cin>>s;s=' '+s;
bool flag=false;
int pos=-1;
for(int i=1;i<=n;i++){
if(s[i]=='0') flag=true;
if(flag && s[i]=='1') pos=i;
}
if(pos==-1){
for(int i=1;i<=n;i++) cout<<s[i];
}
else{
for(int i=1;i<pos;i++) cout<<1;
for(int i=pos;i<=n;i++) cout<<0;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T=1;//cin>>T;
while(T--){
solve();
}
return 0;
}
L 午枫的又一个01串
对于一个 串,如果我们进行的操作区间不在开头也不在结尾,即
满足
,不难
和
从不同变为相同,
和
从不同变为相同。所以当我们对中间部分操作一次,度就会减
。
考虑完中间部分操作的影响,接下来考虑开头和结尾操作会有什么影响:
如果开头 ,则无法操作,同理,如果结尾
也无法操作。
如果开头 ,我们对区间
做一次操作后,由于
前面没有数字了,原本就没有度,所以左端点的改变不会的度产生影响,
和
从不同变为相同,因此此次操作会让度减少
。同理,对结尾
,做一次操作也会让度减少
。
因此,先求出原串的度,优先对串的中间部分进行操作,在判断开头结尾的情况做出相应操作,计算度的减少量即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
int n,m;cin>>n>>m;
string s;cin>>s;s=' '+s;
if(n==1){
cout<<0<<endl;
return;
}
int cnt=0;
for(int i=1;i<n;i++){
if(s[i]!=s[i+1]) cnt++;
}
if(cnt<2){
cout<<cnt<<endl;
return;
}
int ex=0;
if(s[1]=='0') ex++;
if(s.back()=='1') ex++;
int need=0;
need=(cnt-ex)/2;
if(m>=need+ex) cout<<min(1ll,cnt)<<endl;
else{
if(ex==0) cout<<cnt-2*m<<endl;
else if(ex==1){
if(m<=need) cout<<cnt-2*m<<endl;
else cout<<cnt-2*need-min(ex,m-need)<<endl;
}
else if(ex==2){
if(m<=need) cout<<cnt-2*m<<endl;
else cout<<cnt-2*need-min(ex,m-need)<<endl;
}
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T=1;//cin>>T;
while(T--){
solve();
}
return 0;
}
M ACM的数学题真的来了!
问题描述:无限平面上,用直线 圆环 正多边形最多可以将平面划分为几个区块?
直线将一个平面划分为两个部分:显然不会将任何两个直线的交点生成在已存在的交点上,因为可划分区域的直线数量不是最优。
当前的平面数量为 ,存在直线的情况下,无限平面为初始操作平面,但是不存在直线时,只存在封闭图形的操作,因此不断扩大的封闭区域为初始操作平面,因此不存在直线时,还应该加上操作不到的外部无限平面。
考虑直线
第 个直线与
个直线产生
个交点,局面新增
个直线,划分出
个新区域
设
表示
个直线划分的最多区域,则
考虑圆环
第 个圆环与
个圆环产生
个交点,局面新增
个弧线,划分出
个新区域
设
表示
个圆环划分的最多区域,则
,
个圆环与
个直线产生
个交点,局面新增
个直线,划分出
个新区域,则
。
考虑正 多边形(
)
与直线:
<- 每条直线新增 2 个交点
与圆环:
<- 每条边新增 2 个交点
与边数小于
的正多边形:
<- 每条边新增 2 个交点
与自身:
据此只需要按照边数从小到大的方式遍历多边形,采用类似计数 (当然其实不用维护
数组,只需要实时知道有多少多边形比当前的边数少)的方式即可解决。时间复杂度
。
#include <bits/stdc++.h>
using namespace std;
#define int long long
constexpr int mod = 1e9+7;
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n+1, 0);
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
bool valid = 1;
if(a[2]>0)valid=0;
int ans = 1;
(ans += a[1]*(a[1]+1)/2 % mod) %= mod;
(ans += (a[2] * a[1] * 2 % mod + a[2] * (a[2]-1) %mod) %mod) %= mod;
for(int i = 3, sum = 0; i <= n; i++) {
(ans += (sum * a[i] % mod + a[i] * (a[i]-1) * i % mod) % mod) %= mod;
(ans += a[i] * ((a[1] * 2 % mod + a[2] * 2 * i % mod) % mod)) %= mod;
(sum += 2 * a[i] * i % mod) %= mod;
if(a[i]>0)valid=0;
}
if(a[1] == 0 && (!valid))
ans++;
cout << ans << '\n';
return 0;
}