1. 程式人生 > >[2018.10.31 T2] 電梯

[2018.10.31 T2] 電梯

暫無連結

電梯(lift)

題目背景

打完昆特牌後你不準備參加 N O I P NOIP 模擬賽了,因為你有更重要的賽事— N

O G P NOGP (National
Olympiad in Gwent in Provinces)你現在要上電梯去 N N 樓參加 N
O G P NOGP
。在你從 1 1 樓上電梯的同
時,你發現另有一臺空電梯從 1
1
樓同時向 N N 樓向上。

題面描述

N N 層樓中有 M M 層樓 (除了 1 1 層、 N N 層) 被標記了,如果有電梯到達有標記的層數時會停下來 1 s 1s , 然後標記會消失。因為標記消失了,所以下面一臺電梯到這一層時就不會再停了。而且如果你的電梯和旁邊電梯一起到達標記的層數的話,是你的電梯停下來,而旁邊電梯會繼續往上,然後標記消失。在電梯裡的你也可以按下一些內部的按鈕使自己的電梯在某層停下 1 s 1s (除了 1 1 層、 N N 層)。而旁邊的電梯不能讓自己停 1 s 1s

你覺得輸給一臺空電梯非常丟臉,現在求在你不慢於空電梯的情況下最快在什麼時候達到樓頂。若你不能不慢於空電梯,輸出 1 -1 。電梯上一層樓所需時間為 1 s 1s 注意在一層樓你只能停一次

輸入資料

第一行一個 T T 表示資料組數

接下來每行五個數 N M a b c N、M、a、b、c

下面給出生成 M M 層被標記的層數的方法:

f [ i ] i f[i] 表示第i個生成的被標記的層數

f [ 1 ] = c   m o d   ( N 2 ) + 2 f[1]=c\ mod\ (N-2)+2

f [ i ] = ( f [ i 1 ] × a + b )   m o d   ( N 2 ) + 2 f[i]=(f[i-1]\times a+b)\ mod\ (N-2)+2

f [ i ] f [ i ] = 1 若生成的 f[i] 已經被標記了,則f[i]=現在最低的沒有被標記的那一層(第1層除外)

輸出資料

對每行資料輸出一行答案。

樣例資料
INPUT

3
5 3 1 8 2
4 2 6 1 1
7 2 3 1 3

OUTPUT

6
4
7

樣例解釋

第一份資料:(下文 表示你的電梯, 表示空電梯)
一共五層樓,中間三層都被按了按扭
1s 上 2
2s 停, 上 3
3s 上 3, 停 3
4s 主動停 3, 上 4
5s 上 4, 停 4
6s 上 5, 上 5

資料範圍

對於 20%的資料, N 10 N≤10 , M 10 M≤10

對於 60%的資料, N 1000 N≤1000 , M 1000 M≤1000

對於 100%的資料

N 1 0 7 N≤10^7 , M 1 0 7 M≤10^7 , T 10 T≤10 N M + 2 N≥M+2 0 a b c 1000 0≤a、b、c≤1000 N 3 N≥3 M 1 M≥1

題解

仔細想想貪心策略,你會發現答案貌似是跟按按鈕的具體樓層無關的。

m m 為偶數的時候,我們不需要做任何操作,跟著空電梯一起向上,就能每個電梯接一半乘客從而一起到樓頂;當 m m 為奇數時,我們需要在最後一個按按鈕的樓層之前停下,讓空電梯先上去接人,從而一起到樓頂。

注意,因為第一層樓無法停下,所以二樓的乘客我們必須接,當只有二樓被按得時候我們無法與空電梯持平,所以輸出 1 -1

程式碼
#include<bits/stdc++.h>
using namespace std;
int n,m,c,T;
void in(){scanf("%d%d%*d%*d%d",&n,&m,&c);}
void ac()
{
	if(c%(n-2)==0&&m==1)puts("-1");
	else if(m&1)printf("%d\n",n+(m>>1));
	else printf("%d\n",n+(m>>1)-1);
}
int main(){for(scanf("%d",&T);T--;)in(),ac();}