1. 程式人生 > 其它 >位元組跳動歷屆筆試題(2)

位元組跳動歷屆筆試題(2)

技術標籤:常見筆試程式設計題

題目描述

有n個房間,現在i號房間裡的人需要被重新分配,分配的規則是這樣的:先讓i號房間裡的人全都出來,接下來按照 i+1, i+2, i+3, ... 的順序依此往這些房間裡放一個人,n號房間的的下一個房間是1號房間,直到所有的人都被重新分配。

現在告訴你分配完後每個房間的人數以及最後一個人被分配的房間號x,你需要求出分配前每個房間的人數。資料保證一定有解,若有多解輸出任意一個解。

輸入描述:

第一行兩個整數n, x (2<=n<=10^5, 1<=x<=n),代表房間房間數量以及最後一個人被分配的房間號;
第二行n個整數 a_i(0<=a_i<=10^9) ,代表每個房間分配後的人數。

輸出描述:

輸出n個整數,代表每個房間分配前的人數。

示例1

輸入

3 1
6 5 1

輸出

4 4 4

思路:一道思維題,我們需要分三種情況【本題所用圖均來自:官方題解】:

我們假設需要分配的房間為room_i,最後一次被分配的房間為room_x,再分配後房間內最少人數為p_min。

(1)room_i>room_x,此時是下圖的情況:

按照每輪分配原則,room_x+1和room_i之間被分配p_min個人,room_i向後繞回room_x的房間則被分配pmin+1個人,可以計算出room_i的初始人數為 p_min×n+[n-(room_i-room_x)]。

(2)room_i<room_x,此時:

room_i+1到room_x之間被分配p_min+1個人,其他房間被分配p_min個人。room_i初始人數為 pmin×n+(room_x-room_i)。

(3)room_i=room_x,此時:

這時重合房間被分配0人,初始人數為 p_min×n。

從上述三種情況我們可以發現,無論room_i的位置在哪裡,其房間內再分配後的人數一定是最小的,因此我們只需要找到最小人數對應的房間便是room_i的位置,而當有多個最小值出現的時候,則我們從room_x往前退找到第一個出現最小值的位置即為room_i【想想為什麼是這樣】。隨後,根據整數輪次,將每個房間的人數都減去p_min,求出其初始人數。這時只有room_x和room_i重合的情況才會正好分配完,其他情況我們根據最後不足一輪時,兩房間之間相隔房間數即可求出room_i初始房間人數。

#include<stdio.h>
#include<limits.h>
#include<algorithm>
using namespace std;
#define ll long long
int n,x;
ll room[1500005];
int main(void){
    scanf("%d%d",&n,&x);
    ll mn=INT_MAX;
    for(int i=0;i<n;i++){
        scanf("%lld",&room[i]);
        mn=min(mn, room[i]);
    }
    x-=1;
    int pos=x;
    while(room[pos]!=mn)
        pos=pos>0?pos-1:n-1;
    for(int i=0;i<n;i++)
        room[i]-=mn;
    int count=0;
    for(int i=x;i!=pos;i=i>0?i-1:n-1){
        room[i]-=1;
        count+=1;
    }
    room[pos]+=count+n*mn;
    for(int i=0;i<n;i++)
        printf("%lld ",room[i]);
    return 0;
}