icpc济南赛站补题记录
M:煎饼需要煎两面,一口锅能一次性煎k个饼,一共有n个饼需要煎,煎一面饼要一分钟,问你煎完n张饼需要几分钟
如果k>=n两分钟煎完,否则需要(n*2+k-1)/k分钟
G:给你一个x给你一个y,每次能用一个小于当前x的数异或x,使得最终的x=y
思路1;
我们知道,一个数异或自己等于0,一个数异或0等于本身,不考虑大小的话,我们直接让x ^ ( x ^ y)即可,如果x ^ y > x 就先让x ^ y,再 ^ x即可(x<x ^ y)
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long int x,y;
cin>>x>>y;
long long int a=x^y;
if(a>x)
{
printf("2\n");
printf("%lld %lld\n",y,x);
}
else
{
printf("1\n");
printf("%lld\n",a);
}
return 0;
}
C: 思维题,
1,2,3堆的石子各有 a , b , c 堆,合并x堆石子和y堆石子的花费是(x * y) mod 3,问你合并所有的石子需要至少多少花费。
首先3堆的石子怎么合并都是0花费不需要考虑,剩下的石子里,我们希望3的倍数堆的石子堆合并最少的次数(花费最少的费用)出现,所以我们先将1堆和2堆里能合成3堆的合并,花费为2,再将剩下的1堆或2堆里的石子合并,1堆三个三个合并花费为3,2堆三个三个合并花费为6,如果剩下一个,直接合并0花费,如果剩下两个,就将两个合并,花费分别为1和4。
原则就是按照花费少的次序将各堆石子合成3的倍数堆
#include<iostream>
using namespace std;
int main()
{
int a[3];
cin>>a[0]>>a[1]>>a[2];
int ans = 0;
if(a[0]>a[1])
{
ans += 2*a[1];
int tmp = a[0]-a[1];
ans += (tmp/3)*3;
if(tmp%3==2)ans+=1;
}
else{
ans += 2*a[0];
int tmp = a[1]-a[0];
ans += (tmp/3)*6;
if(tmp%3==2)ans+=4;
}
cout<<ans<<endl;
}
D题 区间贪心
n个学生写论文,每个学生能写的字数范围为l,r,每个学生能得到的分数为n-k,k为每个学生写字字数的排名(从大到小),这种形势容易造成内卷,如果所有学生选择内卷,他们会写自己能力范围内最多的字,我们不希望内卷,所以希望所有学生写字的总字数最少,而且使学生的成绩不低于原来的目标,问所有学生的最少总字数为多少。
我们考虑贪心,让尽量多的学生成绩排名相同,即让更多的学生写字字数相同,先对r[ i ]从小到大排序,再按l [ i ] 从大到小排序,这样使得落在l ,r之间的点尽量多。遍历时再去区间内l的最大值即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
struct node
{
int l,r;
}a[N];
int cmp(node x,node y)
{
if(x.r!=y.r)
return x.r<y.r;
else return x.l>y.l;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i].l>>a[i].r;
sort(a+1,a+n+1,cmp);
int sum=0;
int maxl=0;
for(int i=1;i<=n;i++)
{
sum+=max(a[i].l,maxl);
maxl=max(a[i].l,maxl);
}
cout<<sum<<endl;
}