近期最后一场cf了,双休日icpc网络赛之后,就要开始准备数模国赛了,加油吧
A. Fraction
思路:寻找最大最简真分数,题有点长,不过理解后难度不大,枚举判断gcd即可
/*
Author Owen_Q
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int gcd(int a,int b)
{
return b == 0 ? a : gcd(b, a % b);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int a = n/2;a>=1;a--)
{
int b = n - a;
if(gcd(a,b)==1)
{
printf("%d %d\n",a,b);
break;
}
}
}
return 0;
}
B. Maxim Buys an Apartment
思路:寻找最优房,样例有很大提示性作用,所有空房连一起肯定是最差策略,一个租房连两个空房肯定是最优策略,最后特判一下无房情况即可
/*
Author Owen_Q
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(k==0||k==n)
{
printf("0 0\n");
}
else
{
int mininum = 1;
int maxinum = 0;
if(2*k>=n-k)
{
maxinum = n-k;
}
else
{
maxinum = 2 * k;
}
printf("%d %d\n",mininum,maxinum);
}
}
return 0;
}
C. Planning
思路:这题就比较坑了,如果想明白就很简单
简单的并查集问题,每个时间点作为一个集合,将无法起飞的集合并入下一个集合
贪心按延期代价排序,最先满足代价高的,该时间段所属集合即为起飞时间,每次log的复杂度
纯并查集裸题,然而,思路一般不容易想到,大量的时间细化杂乱的细节,最后却发现并查集完美解决
/*
Author Owen_Q
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
typedef struct FLIGHT
{
int time;
int c;
}Flight;
Flight f[maxn];
int pre[2*maxn];
int takeoff[maxn];
//bool takeoff[2*maxn];
int finds(int x)
{ //寻找
int r = x;
while(pre[r]!=r)
{
r = pre[r];
}
int i=x ,j;
while(pre[i]!=r)
{ //路径压缩
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
void join(int x,int y)
{ //将两个集合合并
int fx = finds(x);
int fy = finds(y);
if(fx!=fy)
{
pre[fx] = fy;
}
}
bool cmp(const Flight &a,const Flight &b)
{
if(a.c>b.c)
{
return true;
}
else
{
return false;
}
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
//memset(takeoff,false,sizeof(takeoff));
//takeoff[k+1] = true;
pre[n+k+1] = n+k+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&f[i].c);
f[i].time = i;
pre[i] = i;
/*else
{
takeoff[i+1] = true;
}*/
}
for(int i=n+1;i<=k+n;i++)
{
pre[i] = i;
//takeoff[i] = true;
}
for(int i=1;i<=k;i++)
{
join(i,k+1);
}
sort(f+1,f+n+1,cmp);
long long sum = 0;
for(int i=1;i<=n;i++)
{
//cout << f[i].c << endl;
/*if(takeoff[f[i].time])
{
takeoff[f[i].time] = false;
join(f[i].time,f[i].time+1);
}
else
{
}*/
sum += (long long)(finds(f[i].time) - f[i].time) * (long long)(f[i].c);
/*cout << sum << endl;
for(int j=1;j<=8;j++)
{
cout << pre[j] << " ";
}
cout << endl;
cout << f[i].time<<"*"<<finds(f[i].time)+1<<endl;*/
takeoff[f[i].time] = finds(f[i].time);
join(f[i].time,finds(f[i].time)+1);
}
printf("%I64d\n",sum);
for(int i=1;i<n;i++)
{
printf("%d ",takeoff[i]);
}
printf("%d\n",takeoff[n]);
}
return 0;
}
最后,比赛加油