练习20200330

本来打算练习贪心,在蓝桥杯训练系统里找了一道(其实安排了好几道)
在这里插入图片描述
果然我还是高估了自己的实力,不说了上题!

试题 算法训练 Beaver’s Calculator

资源限制
时间限制:3.0s 内存限制:256.0MB
问题描述
  从万能词典来的聪明的海狸已经使我们惊讶了一次。他开发了一种新的计算器,他将此命名为"Beaver’s Calculator 1.0"。它非常特别,并且被计划使用在各种各样的科学问题中。
  为了测试它,聪明的海狸邀请了n位科学家,编号从1到n。第i位科学家给这个计算器带来了 ki个计算题。第i个科学家带来的问题编号1到n,并且它们必须按照编号一个一个计算,因为对于每个问题的计算都必须依赖前一个问题的计算结果。
  每个教授的每个问题都用一个数 ai, j  来描述,i(1≤i≤n)是科学家的编号,j(1≤j≤ ki )是问题的编号, ai, j  表示解决这个问题所需资源单位的数量。
  这个计算器非常不凡。它一个接一个的解决问题。在一个问题解决后,并且在下一个问题被计算前,计算器分配或解放资源。
  计算器中最昂贵的操作是解放资源,解放远远慢于分配。所以对计算器而言,每一个接下来的问题所需的资源不少于前一个,是非常重要的。
  给你关于这些科学家所给问题的相关信息。你需要给这些问题安排一个顺序,使得“坏对”尽可能少。
  所谓“坏对”,就是相邻两个问题中,后一个问题需求的资源比前一个问题少。别忘了,对于同一个科学家给出的问题,计算它们的相对顺序必须是固定的。
输入格式
  第一行包含一个整数n,表示科学家的人数。接下来n行每行有5个整数,ki, ai, 1, xi, yi, mi (0 ≤ ai, 1 < mi ≤ 109, 1 ≤ xi, yi ≤ 109) ,分别表示第i个科学家的问题个数,第1个问题所需资源单位数,以及3个用来计算 ai, j 的参量。ai, j = (ai, j - 1 * xi + yi)mod mi。
输出格式
  第一行输出一个整数,表示最优顺序下最少的“坏对”个数。
  如果问题的总个数不超过200000,接下来输出 行,表示解决问题的最优顺序。每一行两个用空格隔开的整数,表示这个问题所需的资源单位数和提供这个问题的科学家的编号。
样例输入

2
2 1 1 1 10
2 3 1 1 10

样例输出

0
1 1
2 1
3 2
4 2

数据规模和约定
  20%的数据 n = 2, 1 ≤ ki ≤ 2000;
  另外30%的数据 n = 2, 1 ≤ ki ≤ 200000;
  剩下50%的数据 1 ≤ n ≤ 5000, 1 ≤ ki ≤ 5000。
 
 
看了快有两个小时
得到的信息: n个科学家,每人有ki个问题,给出了每人第一个问题的资源单位数,三个参量xi、yi、mi,之后的问题所需资源单位数满足ai, j = (ai, j - 1 * xi + yi)mod mi。要求不改变对于单个科学家的问题的顺序,改变科学家之间的问题的顺序使得“坏对”最少。
思路: 不改变科学家自身问题的顺序,又要使坏对最小,设未排序前科学家自身问题的坏对数为xi。这里的坏对可以理解为一次跳跃。(重点)对于每个科学家自身的问题,每跳跃一次,就把跳跃之前的顺序数组划分为一个层次,这样就把每个科学家的问题划分为xi层。那么当把不同科学家处于同一层的问题进行绝对排序,再按层次顺序输出,就可以保证不改变科学家自身问题的顺序,并且最优顺序下的坏对数就是科学家中xi的最大值。代码实现就可以用一个结构体保存每个问题所属的科学家所需资源单位数层次,最后将层次相同的问题根据所需资源单位数排序,最后按层次顺序输出。

借鉴了sort函数
AC代码():

#include <bits/stdc++.h>
typedef long long ll; 
using namespace std;
#define kk 200000
struct source
{
    int a;//表示所属科学家 
    int b;//表示所需资源单位数 
    int c;//表示层次 
}s[kk];
int cmp(source a,source b)//**该排序方法借鉴**这里非常巧妙!如果层数相等在同一层里我们就按照所需资源单位数排序,如果资源单位数相同就按照科学家编号排序,否则就按层数排序
{
    if(a.c==b.c)
        return a.b<b.b||(a.b==b.b&&a.a<b.a);
    return a.c<b.c;
}
int main()
{
	ll n,a,k,x,y,m;//n为科学家人数,a为问题资源单位数,k为问题数,xym为三个参数 
    int ans=0,con=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int t=0;
        cin>>k>>a>>x>>y>>m;
        for(int j=0;j<k;j++)//获取每个科学家的信息 
        {
        	ll temp; 
            if(con<=kk)//题目要求范围 
			{
				s[con].a=i;
				s[con].b=a;
				s[con].c=t;
				con++;
			}
            temp=(x*a+y)%m;//计算下一个问题所需资源单位数 
            if(temp<a)t++;//判断是否跳跃 
            a=temp;
        }
        ans=max(ans,t);//获得最大层数。 
    }
    cout<<ans<<endl;
    if(con<=kk)
    {
        qsort(s,s+con,cmp);
        for(int i=0;i<con;i++)
        {
            cout<<s[i].b<<' '<<s[i].a<<endl;
        }
    }
}

我什么时候才能拥有想出这个sort的人的脑回路(不然归并代码太长我懒)
😁


试题 算法训练 最大最小公倍数

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少。

输入格式
输入一个正整数N。

输出格式
输出一个整数,表示你找到的最小公倍数。
样例输入
9
样例输出
504
数据规模与约定
1 <= N <= 106

这一题看着看挺简单结果wa了两发。
思路: 连续三个数存在奇偶情况,相邻的偶数求出来肯定除过二,求最大的三个互质数
仔细一想,分类讨论:

  1. N为奇数时就是N,N-1,N-2这三个数的乘积(相邻的两个奇数肯定互质,相邻的两个数也互质
  2. N为偶数时,因为取三个数,所以情况稍微复杂一点。跳过一个最小的偶数,最小公倍数为N,N-1,N-3三个数的乘积。跳过N-2是因为N和N-2一定可以共同约掉一个2(ab/2<=a(b-1))。但是如果N可以被3整除,那么N和N-3也一定可以共同约掉一个3,这时最大互质的三个数是N-1,N-2,N-3。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll n,ans;
    cin>>n;
    if(n%2==0){
    	if(n%3==0)cout<<((n-1)*(n-2)*(n-3))<<endl;
    	else cout<<((n-1)*(n)*(n-3))<<endl;
	}
	else cout<<((n-1)*(n-2)*(n))<<endl;
}

水题还是多想想细节,不然比赛的时候白白WA在水题上还是很难受的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值