鉴于此次大部分题比较水,这次写个部分题解吧。
4个小时做了9个题,都是做的水题...接下来分析点正经题:
问题 B:没事找事想排队
- 听说很多小伙伴这个题卡了好久....emmm....卡在哪了呢?先后顺序!题目可没说编号跟来的先后顺序有关系啊...这个做sort判断即可。熟练运用sort,你会发现sort真的是神奇!
- 实际的代码无非就是输入->排序->输出->AC
- 关键在于cmp的编写,按照题目给出的条件写就行
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct person
{
int bh; //编号
int age; //年龄
int time; //来的时间
} s[30004];
int n;
bool cmp(person a, person b)
{
if (a.age < 60 && a.age > 6 && b.age < 60 && b.age > 6)
return a.time < b.time;
else if (a.age <= 6 && b.age <= 6)
{
if (a.age == b.age)
return a.time < b.time;
else
return a.age < b.age;
}
else if (a.age <= 6 || b.age <= 6)
return a.age < b.age;
else if (a.age >= 60 && b.age >= 60)
{
if (a.age == b.age)
return a.time < b.time;
else
return a.age > b.age;
}
else
return a.age > b.age;
}
void input()
{
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%d%d", &s[i].bh, &s[i].age);
s[i].time = i; //时间就是他的输入的顺序
}
}
void output()
{
for (int i = 0; i < n; i++)
cout << s[i].bh << endl;
}
int main()
{
input();
sort(s, s + n, cmp);
output();
return 0;
}
问题C:有钱shao的毒瘤国王
这个题读完题很快能明白题意,我们无非就是找到一个数num的最大的质因数,只是num的范围比较大而已,赛后受朋哥指点觉得原来这么简单
- 如果num本身是个质数直接输出1就可以,问题是当num不是质数的时候
- 方法1:从 num-1 枚举到 1 如果找到一个数 i 能整除num且这个数是质数,妥了,他就是我们要找的数输出 num / i 即可,但是毒瘤超时
- 方法2:先找这个num的因数,存起来按从大到小的顺序,从最大的枚举,直到找到一个质数。这样AC。
- 需要注意的是,在本题明确说明2是最小的质数,不必纠结1的问题,输出0的情况就是num最大的质因数是1的时候,比如说num=1;
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int isp(int k)
{
if (k < 4)
return 1;
for (int i = 2; i <= sqrt(k); i++)
if (k % i == 0)
return 0;
return 1;
}
int ok;
int num;
int ans[100000];
int main()
{
int t;
cin >> t;
while (t--)
{
int k = 0;
cin >> num;
if (isp(num))//判断num本身是质数,直接输出1
cout << 1 << endl;
else
{
for (int i = 1; i <= sqrt(num); i++)
if (num % i == 0)//对num开放找出所有因数,存到ans数组里
{
ans[k++] = i;
ans[k++] = num / i;
}
sort(ans, ans + k);//对所有因数排个序
for (int i = k - 1; i >= 0; i--)//从大到小枚举因数,如果这个因数同时是质数,那么就是我们要的
if (isp(ans[i]))
{
ok = ans[i];
break;
}
if (ok > 1) //判断我们找到的这个最大质因数是不是1
cout << num / ok << endl;
else
cout << 0 << endl;
}
}
return 0;
}
问题D:毒瘤市长爱建楼
- 仔细想想,是不是新生赛记蒜几何的简单版??woc简直一毛一样啊,数据还变水了。
- 这里提供一下记蒜几何的题解,大家可以再回忆一下
- 同样的原理,因为楼高是不重复的,且都在1~n之间,我们把每个楼高抽象为一个坐标点,他的坐标就是他本身的高度,然后整条数轴上找就行了,如果确定了三个点之中的两个点,第三个点一定是确定的,O(N^2)解决方案:
#include <iostream>
#include <cstring>
using namespace std;
int t;
int n;
int ans;
int mxn;
int a[2005];
int c[2005];
int main()
{
cin >> t >> n;
for (int k = 1; k <= t; k++)
{
int tot = 0;
memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
c[a[i]] = i;
}
for (int i = 2; i < n; i++)
{
for (int j = 1; j < i; j++)
{
int z = 2 * a[i] - a[j];
if(z>=1 && z<=n && c[z]>i)
tot++;
}
}
if (tot > mxn)
{
mxn = tot;
ans = k;
}
}
cout << ans << " " << mxn;
return 0;
}
问题H:闲的小华不敲代码组玩具
- 二分答案
- 这里暂时不做解读,只贴出代码,12月12日晚讲二分法,到时候就会明了...
#include <iostream>
#include <algorithm>
using namespace std;
struct toy
{
int a;
int b;
int c;
} s[1000006];
int n, m;
int cnt;
int ans = 0;
int sum;
int k[1000006];
bool cmp(toy x, toy y)
{
return x.c < y.c;
}
int ifok(int k) //判断二分出的答案是否可行
{
int mm = 0;
for (int i = 0; i < n; i++)
{
if (s[i].c >= k)
return m - mm;
mm += k * s[i].b - s[i].a;
if (m - mm < 0)
return m - mm;
}
return m - mm;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> s[i].a;
for (int i = 0; i < n; i++)
{
cin >> s[i].b;
s[i].c = s[i].a / s[i].b;
sum += s[i].b;
}
sort(s, s + n, cmp);
for (int i = 0; i < n; i++)
{
if (k[cnt] != s[i].c)
k[++cnt] = s[i].c;
}
int mm = ifok(k[cnt] + 1);
if (mm == 0)
cout << cnt + 1;
else if (mm > 0)
cout << mm / sum + k[cnt] + 1;
else //本题核心:二分答案
{
int l = 0;
int r = k[cnt];
while (l <= r)
{
int mid = (l + r) / 2;
if (ifok(mid) >= 0)
{
ans = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
cout << ans;
}
return 0;
}