题目1内卷
期末有n个同学写论文,第i个人写论文的字数在 [ Li , Ri ] 之间,定义wi为某个同学写的字数。
所以Li≤wi≤Ri
而成绩的得分是非常有趣的,第i个同学gi的论文得分为n-Ki
Ki是比当前这个人的论文字数多的人数
每个人都想写尽可能多的字,因为每位同学都想尽可能得到更高的得分。
所以很容易想到让wi=Ri即可。
但是zks发现了有一个有趣的现象
假设对于每位同学来说,∀i∈[1,n] Li=1000,Ri=10000. 那么在最积极情况下,每位同学都写10000字,即wi=10000.
所以每位同学的得分都为n-0(ki=0,因为没有被任何同学超过)。但是如果每位同学都写1000字,每个人的得分仍然为n-0.
这种现象被称之为内卷
感受到内卷的威力了嘛?!
现在让你尽可能降低1~n位同学所有字数总和的情况下,即min{w1+w2+…+wn} 的同时保证每位同学不能低于在尽自己最大努力时所能得到的分数
你能帮帮zks解决这个问题吗?
输入
第一行有一个正整数n
接下来有n行,第i行有两个正整数Li,Ri
1≤n≤1e5
1≤Li≤Ri≤1e9
输出
输出最小的 w1+w2+…+wn的值
样例输入
3
1 10000
1 10000
1 10000
样例输出
3
大意是说找到一个数,是所有学生能拿到他付出最小的努力能拿到的最高名次,且保证在这条件下所有人的字数最少。
下面是代码
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f
typedef long long ll;
const int M = 1e5 + 10;
#define bug(a) cout<<endl<<"*"<<a<<endl;
struct node
{
ll l, h;
}arr[M];
bool cmp(node a,node b) {//先将最多努力的排一下,要是一样的最大
if (a.h == b.h) {//努力,那么可以将那群人最少的努力最大的放前面
return a.l > b.l;//要是需要加快编译速度,可以用这个来跳过
} //毕竟这群人最大的都比那个小嘛
else return a.h < b.h;
}
int main()
{
ll n, i, j,ans=0;
cin >> n;
for (i = 1; i <= n; i++) {
cin >> arr[i].l >> arr[i].h;
}
sort(arr, arr + n+1, cmp);//将序排好
int min = 0;
for (i = 1; i <= n; i++) {
if (arr[i].l <= min) {//最大努力的那个值比他大的那个人要是
ans += min;//最小努力比他的最小努力还小可以定为一级
}//这就相当于拿最少努力拿最大名词且字数和最小
else {
min = arr[i].l;//如果最小的比你那个等级的要大,那么就
ans += min;//换到下一等级去了,以此类推。
}
}
cout << ans << endl;
}
我这属于代码简化版,好理解的和计算效率快的,还请参考要代码点这
发个牢骚
一开始题目看错了,(同时保证每位同学不能低于在尽自己最大努力时所能得到的分数)这句话让我百思不得其解,没明白这意思,后面看了我打算打冲省一的浩哥的代码,才发现可以往前挪一个等级,我之前思路一直都是往后挪一个等级(因为满足最小努力最高名次嘛),所以一直不明白这最小字数又怎么满足,看样子多读书还是好的啊,尤其是语文
题目2俊哥爬山
你看我还有机会吗
刘俊学长在一个深山老林里冒险,这里到处都是山,第i座山的高度记为hi
当hi-1<hi且hi+1<hi时,刘俊学长将会讨厌这座山,也就是第i座山。因为它需要消耗更多的体力翻越。
然而zks是一位魔法师,他可以使一座山凭空消失,而它旁边的两座山会神奇般的连接起来。
例如有7座山,高度为 1 9 1 9 8 1 0 当对第三座山施加魔法时,剩下的六座山为1 9 9 8 1 0
zks希望在释放魔法后,刘俊学长讨厌的山会尽可能的变少。那么最少会有多少座山令刘俊学长讨厌呢? 魔法只能释放一次。
输入
有多组样例测试
第一行为一个整数n,代表有n座山
第二行包含n个正整数 h1,h2,…,hn,代表山的高度
1≤n≤1e5, 0≤hi≤1e9
输出
在释放魔法后,刘俊最少会讨厌的山的数量
样例输入
6
1 1 4 5 1 4
7
1 9 1 9 8 1 0
10
2 1 4 7 4 8 3 6 4 7
样例输出
1
0
2
其实这道题超级简单,题目一直看错,该戴眼镜了……
就是消除一座山,使剩下的山最少,上面的数字是离地高度要大于两边的高度才是一座山,而不是一个高度一座山(不要向我一样蠢)
思路是给他把所有山的坐标找出来保存在一个数组里面,再起一个for循环去判断,有个细节:山一样高的时候输出应该是0,而不是1。
下面是代码
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f
typedef long long ll;
#define bug(a) cout<<endl<<"*"<<a<<endl;
const int m = 1e5 + 10;
int arr[m],brr[m];
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int n, i, j;
while (cin >> n) {
memset(arr, 0, sizeof(arr));//记得清零
memset(brr, 0, sizeof(brr));
int k = 0;//记山有多少座
for (i = 1; i <= n; i++)
cin >> arr[i];
for (i = 1; i <= n; i++) {
if (arr[i] > arr[i - 1] &&arr[i-1]&&arr[i+1]&& arr[i] > arr[i + 1]) {
brr[++k] = i;
}
}
int ans1 = k,ans=MAX;//ans1是给介值,用来得到ans的最小的,因为可能是k-1也有可能是k-2
if (k == 0)cout << "0" << endl;//山为0时输出为0
else {
for (i = 1; i <= k; i++) {
if (arr[brr[i - 1]]&& brr[i]- brr[i - 1] == 2) {//如果两座山中间那个消掉可以令两座山连在一起且高度相同,相当于消去两座山
if (arr[brr[i]] == arr[brr[i - 1]])ans = min(ans1-2,ans);
}
else if (arr[brr[i] - 2] && arr[brr[i] + 2] && arr[brr[i] - 1] && arr[brr[i] + 1] && ((arr[brr[i] - 1] > arr[brr[i] + 1] && arr[brr[i] - 1] > arr[brr[i] - 2]) || (arr[brr[i] + 1] > arr[brr[i] - 1] && arr[brr[i] + 1] > arr[brr[i] + 2]))) {
//如果消去一座山以后会生成一座新的山,那么相当于没变
ans = min(ans, ans1);
}
else { ans = min(ans, ans1 - 1); }//其他情况就是可以少一座山
}
cout << ans << endl;
}
}
return 0;
}
题目3最小互质数
我们定义两个数的互质数当且仅当gcd(a, b) = 1。
现在L手里有n个数,分别为a1,a2,a3 ……an-1,an 。
问,没有在这n个数中出现过并且与这n个数都互质的最小的数是多少。
LL觉得这个问题太简单了,于是她把这个问题交给你来解决。
输入
第一行一个数n (1 ≤ n, ai ≤ 10^5)
接下来n行,每行一个数,分别代表a1,a2,a3 ……an-1,an 。
输出
输出一行代表答案
样例输入
5
1
2
3
4
5
样例输出
7
提示
没有在这n个数中出现的数有:6,7,……
6与2, 3, 4不互质,最小的与这n个数互质的数就是7了。
其实把所有质数取出来就行只是这道题还有个1也要算进来,特殊一点
这里给一个取出质数的代码
void prime()
{
int tot=1;
memset(v,true,sizeof(v));v[1]=false;
for(int i=2;i<N;++i)//n为素数的最大界限,自己定义
{
if(v[i]) ans[tot++]=i;//ans数组存所有素数
for(int j=1;(j<tot)&&(i*ans[j]<N);++j)
{
v[i*ans[j]]=false;
if(i%ans[j]==0) break;
}
}
}
接下来就是这道题的代码呈上
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f
typedef long long ll;
#define bug(a) cout<<endl<<"*"<<a<<endl;
const int m = 1e5 + 10;
int arr[m],brr[m];
bool crr[m];
map<int, bool>p;
void juge(int &cnt)
{
int i, j;
cnt = 1;
memset(crr, true, sizeof(crr));
//crr[1] = false;
brr[cnt++] = 1;//这里是将1放进这个存素数的数组里,所以上面被注释了
for (i = 2; i < m; i++) {
if (crr[i])brr[cnt++] = i;
for (j = 2; (j < cnt) && (brr[j] * i < m); j++) {
crr[i * brr[j]] = false;
if (i % brr[j] == 0)break;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int n, i, j,cnt;
cin >> n;
for (i = 1; i <= n; i++) {
cin >> arr[i];
p[arr[i]] = true;//map函数初始为false,所以出现的数全部定为true就行
}
juge(cnt);//进行素数的收集
for (i = 1; i <cnt; i++) {
int flag = 1;
if (p[brr[i]] == true)continue;//如果有一样的就跳过
for (j = 1; j <= n; j++) {
if (arr[j] %brr[i]==0&&i!=1) {//输入的数刚好是此素数的倍数也不行
flag = 0;//因为他们俩最大公约数不是1,例如3是素数,9和3便不满足条件了
break;
}
}
if (flag)break;
}
cout << brr[i] << endl;
return 0;
}
题目4放置游戏
zks正在和mqj玩一个数字游戏,游戏规则如下
zks在水平数轴上放置了n个正整数,第i个数为ai
mqj放置了m个正整数,第j个数为bj
现在由瑶姐在水平数轴上任意位置放置一个实数c
如果存在一个ai ( 1≤i≤n) ,对所有bj (1≤j≤m)来说,都满足| c-ai |<| c-bj |时,那么zks将获得一分。
而瑶姐希望zks分数尽可能高,所以实数c的放置位置就至关重要。
如果zks得分为0,输出Impossible
请你帮瑶姐计算zks最高得分为多少
输入
有多组测试数据
第一行为两个正整数n,m (1≤n,m≤1e5)
第二行为n个正整数a1,a2…an
第三行为m个正整数b1,b2…bm
1≤ai,bi≤1e9
输出
输出zks最高的得分,如果为无法得分,则输出Impossible
样例输入
2 2
2 3
1 4
6 5
2 5 3 7 1 7
3 4 3 1 10
1 1
7
7
样例输出
2
3
Impossible
提示
第一个例子:当c=2.5时,zks将得2分
第二个例子: 当c=7时,zks将得3分
第三个例子:无论瑶姐把实数c放在哪 ,zks都无法得到分。
思路:(将公式转成点到每个点的距离就好理解了)
将mqj的数与0和无限大一起分成m+1个区间(前提是没有重复的,要是有重复的可以用unique函数弄掉unique)然后再把zks的数放进去,然后取得zks的数能放进区间最多的个数就行。
举个例子(已经排好序了)
zks a[1],a[2],a[3]
mqj b[1],b[2],b[3]
将mqj的三个数和0和无穷大一起排,得到3+1个区间因为有3+1个数嘛,
然后假设zks三个数都比mqj的小,那么取一个比a[1]还小的数k,mqj的所有数便都比zks的数离k远。
如果zks的数有两个在a[1]和a[2]之间,取a[1]和a[2]中间那个数h,那么张克胜那两个数将会比mqj所有的数都里h近,并且因为是两个,比另外一个多,所以最多是2.
下面是代码
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f3f
typedef long long ll;
#define bug(a) cout<<endl<<"*"<<a<<endl;
const int M = 1e5 + 10;
ll arr[M], brr[M];
map<ll,ll>node;//标记点,标记zks的数是否和mqj的数相同
queue<ll >p;//队列
int main()
{
ll n, m, i, j;
while (cin >> n>>m)
{
while (!p.empty()) {//将队列清空,或者在这个循环里面创造队列
p.pop();//这样循环一次创建一次,都不用清空
}
for (i = 1; i <= n; i++)
cin >> arr[i];
for (j = 1; j <= m; j++) {
cin >> brr[j];
node[brr[j]] = 1;//mqj的数都标记1
}
brr[m + 1] = 0;
brr[m + 2] = MAX;//将这两个数放进去再排序
sort(arr + 1, arr + n + 1);
sort(brr + 1, brr + 3 + m);
for (i = 1; i <= n; i++) {
if (!node[arr[i]])
{
p.push(arr[i]);//将与mqj不重合的数放进队列
}
}
ll len = unique(brr + 1, brr +m+ 3) - (brr+1);//看前面给的链接,有解释
//去除重复元素并返回非重复元素的下个地址减去首地址等于长度
ll ans = 0;
for (i = 2; i <= len; i++) {
ll num = 0;
while (!p.empty()) {
if (p.front() > brr[i - 1] && p.front() < brr[i]) {
num++;
p.pop();//在此区间就加一个数,找到最多的数就是答案
}
else break;
}
ans = max(ans, num);
}
if (ans == 0)cout << "Impossible" << endl;
else cout << ans << endl;
}
return 0;
}
题目5排名统计