您的位置:首页 > 编程语言 > Go语言

蓝桥杯- 算法训练-Beaver's Calculator

2016-12-27 13:45 323 查看

                                                         算法训练
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<
d40f
/span> ≤ 5000。

思路:由于顺序不可逆,每个科学家的最小“坏对”是确定的,将所有科学家的“坏对”记为 aans ,aans的最大值即为 ans。 我们可以将“坏对”较少的科学家的问题 往 最多的科学家的问题 中插入即可。注意:1)long long  2)要中间逐层排序输出,不能在最后全部输出。

#include <queue>#include <functional>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <stack>#include <vector>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>#include <assert.h>#define REP(i,k,n) for(int i=k;i<n;i++)#define REPP(i,k,n) for(int i=k;i<=n;i++)#define scan(d) scanf("%d",&d)#define scann(n,m) scanf("%d%d",&n,&m)#define mst(a,k)  memset(a,k,sizeof(a));#define LL long long#define eps 1e-8#define INF 0x3f3f3f3f#define mod 1000000007using namespace std;#define N 5005#define M 200005LL k1
,k2
,a
,x
,y
,m
,num
;struct node{  LL num,index;                                 //num 代表问题消耗的资源量 , index 表示问题属于 第 index 个科学家   bool friend operator <(node a,node b){   return a.num > b.num;                       // 按消耗资源量从小到大排序   }}now,nex;priority_queue<node>que;                       //  用队列实现排序输出int main(){   int n;   scan(n);   int sum = 0;   REPP(i,1,n){      scan(k1[i]);                             //k1[i] 第i个科学家的问题数 k2[i]第i个科学家已经处理的问题数      scann(a[i],x[i]);                        //a[i]  第i个科学家当前问题消耗的资源      scann(y[i],m[i]);      sum+=k1[i];                              //用 sum记录总问题数   }   bool flag = 0;   if(sum <= 200000) flag =1;                  //如果总问题数大于 200000 不用输出   int ans = 0;                                 //记录 所有科学家的“坏对”中最大的那个   REPP(i,1,n){   int aans = 0;                                 //科学家的坏对   LL kk,aa;   kk=1;aa=a[i];      while(kk < k1[i]){      LL w = (aa * x[i] + y[i]) % m[i];      if(w < aa) aans++;                          //从大变小 即一个 “坏对”      aa = w;      kk++;   }   ans = max(aans,ans);   }   cout<<ans<<endl;                                //先输出“坏对”数   int tol = 0;                                     //已经处理的问题数 while(tol<sum){ REPP(i,1,n){ if(k2[i] < k1[i]){ //第i个科学家的问题还未处理完 now.num = a[i]; now.index = i; if(flag) que.push(now); //如果要输出,则入队 tol++; k2[i]++; a[i] = (a[i] * x[i] + y[i]) % m[i]; while(a[i] >= now.num && k2[i] < k1[i]){ //每位科学家的问题一层一层进行处理,即当 a[i] < now.num,出现“坏对”停止   now.num = a[i]; if(flag) que.push(now); //如果要输出,则入队 tol++; k2[i]++; a[i] = (a[i] * x[i] + y[i]) % m[i]; //求出下一个要解决问题所需要的资源量 a[i]  }  }  }  if(flag){   while(!que.empty()){ //一层一层“坏对”进行处理,从而实现问题的插入      now = que.top(); que.pop();  cout<<now.num<<" "<<now.index<<endl;   }  } }}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息