有n个房间,现在i号房间里的人需要被重新分配,分配的规则是这样的:先让i号房间里的人全都出来,接下来按照 i+1, i+2, i+3, ... 的顺序依此往这些房间里放一个人,n号房间的的下一个房间是1号房间,直到所有的人都被重新分配。
现在告诉你分配完后每个房间的人数以及最后一个人被分配的房间号x,你需要求出分配前每个房间的人数。数据保证一定有解,若有多解输出任意一个解。
有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个整数,代表每个房间分配前的人数。
3 1 6 5 1
4 4 4
import java.util.Scanner; /** * <a href=https://interview.nowcoder.com/questionTerminal/43068a1013b4417a85c2c2ce8b18159e>牛客描述</a> * 思路:分配后的房间里,人数最少的那一个房间就是i号房间。如果有多个房间人数最少,则取x号房间往前数的第一个人最少的房间。综上:无论哪种情况,从x房间往前数找到的第一个人最少的房间就是i号房间。 * 找出i号房间后,就很容易求出之前的人数了。首先根据i号房间最后的人数确定完整的轮数,然后从x号往前再减去最后不足一轮的部分,然后把多出的人数全部补到第i个房间,就结束了 * @author LBW */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int x = scanner.nextInt() - 1; long[] room = new long[n]; long min = Long.MAX_VALUE; for (int i = 0; i < n; i++) { room[i] = scanner.nextInt(); if (room[i] < min) min = room[i]; } //get min_index int minIndex = x; while (room[minIndex] != min) { minIndex = minIndex > 0 ? minIndex - 1 : n - 1; } // remove the round number. for (int i = 0; i < n; i++) { room[i] -= min; } // remove the tail int remain = 0; for (int i = x; i != minIndex; i = i > 0 ? i - 1 : n - 1) { room[i] -= 1; remain += 1; } room[minIndex] += remain + n * min; //print the result for (int i = 0; i < n; i++) { System.out.print(room[i] + " "); } } }
#include <bits/stdc++.h> using namespace std; int main(){ int n, x; scanf("%d%d", &n, &x); long a[n], s=0, Min=LONG_MAX; for(int i=0;i<n;i++){ scanf("%ld", &a[i]); if(a[i] < Min) Min = a[i]; } int k = x-1; while(a[k] != Min) k = (k+n-1)%n; for(int i=0;i<n;i++) a[i] -= Min; for(int i=x-1;i!=k;){ a[i]--; s++; i = (i+n-1)%n; } a[k] += s + n*Min; for(int i=0;i<n;i++) printf("%ld ", a[i]); return 0; }
package main import ( "fmt" ) func main() { var n, x int _, err := fmt.Scanf("%d %d", &n, &x) for err == nil { x-- rooms := make([]int, n) if n == 0 { _, err = fmt.Scanf("%d %d", &n, &x) continue } fmt.Scan(&(rooms[0])) min := rooms[0] for i := 1; i < n; i++ { fmt.Scan(&(rooms[i])) if rooms[i] < min { min = rooms[i] } } for i := 0; i < n; i++ { rooms[i] -= min } p := x i := min * n for rooms[p] != 0 { rooms[p]-- p = (p + n - 1) % n i++ } rooms[p] += i for _, room := range rooms { fmt.Printf("%d ", room) } fmt.Println() _, err = fmt.Scanf("%d %d", &n, &x) } }
#include<iostream> #include<cstdio> #include<vector> #include<cmath> int maxn= 1000000000; using namespace std; int main(){ int n,x; vector<int> r; scanf("%d %d",&n,&x); int temp; x--; scanf("%d",&temp); int min=maxn; int minD=x; int t=1; for(int i=0;i<n;i++){ r.push_back(temp); scanf("%d",&temp); if((min==temp&&abs(i+1-x)<abs(minD-x))||min>temp){ min=temp; minD=i+1; } } int i=0,count=min+1; if(minD<=x){ for(i=0;i<minD;i++){ r[i]-=min; count+=min; } for(i=minD+1;i<x;i++){ r[i]-=min+1; count+=min+1; } for(i=x+1;i<n;i++){ r[i]-=min; count+=min; } } else{ for(i=0;i<x;i++){ r[i]-=min+1; count+=min+1; } for(i=x+1;i<minD;i++){ r[i]-=min; count+=min; } for(i=minD+1;i<n;i++){ r[i]-=min+1; count+=min+1; } } r[x]-=min+1; r[minD]+=count; for(int i=0;i<n;i++) printf("%d ",r[i]); return 0; }
10 个1000000000过不了:(
数字太大了:(
#include <iostream> #include <climits> using namespace std; int main() { int n, x; cin >> n >> x; auto as = new unsigned long long[n]; int min = 0; for (int i = 0; i < n; ++i) { cin >> as[i]; if (as[i] < as[min]) { min = i; } else if (as[i] == as[min] && i < x) { min = i; } } unsigned long long rounds = as[min]; for (int i = 0; i < n; i++) { as[i] -= rounds; } unsigned long long moved = rounds * n; x--; while (x != min) { --as[x--]; ++moved; if (x < 0) { x = n - 1; } } as[min] = moved; for (int i = 0; i < n; i++) { cout << as[i] << ' '; } }
#include <bits/stdc++.h> using namespace std; int main(int argc,char** argv){ ios_base::sync_with_stdio(false); cin.tie(NULL); int n,x,i,j; cin>>n>>x; long input[n],min=1000000009; for(int i=0;i<n;i++){ cin>>input[i]; if(input[i]<min) min=input[i]; } i=x-1; while(input[i]!=min) i=(i+n-1)%n; for(int j=x-1;j!=i;j=(j+n-1)%n) input[j]--; for(int j=0;j<n;j++) input[j]-=min; input[i]=n*min+(x-1-i+n)%n; for(int i=0;i<n;i++) cout<<input[i]<<" "; }
#include<iostream> #include<stdio.h> #include<string> #include<cstring> #include<limits.h> #include<math.h> #include<algorithm> #include<vector> using namespace std; int main() { int n,x; cin>>n>>x; vector<long long> arr(n,0); long long minnum=INT_MAX; for(int i=0;i<n;i++) { cin>>arr[i]; minnum=min(minnum,arr[i]); } for(int i=0;i<n;i++) { arr[i]-=minnum; } int pos=x-1; long long ans=minnum*1L*n; while(arr[pos]!=0) { ans++; arr[pos]--; //原来分配给该房间的人还给第i个 pos=(pos+n-1)%n; //往前推 } arr[pos]=ans; for(int i=0;i<arr.size()-1;i++) cout<<arr[i]<<" "; cout<<arr[arr.size()-1]<<endl; return 0; }
#include<iostream> using namespace std; int main(void) { int n, m; cin >> n >> m; int* arr; arr = new int[n]; for (int i = 0; i < n; i++) { cin >> arr[i]; } long long sum = 0, minx; for (int i = m - 1; i >= 0; i--) { arr[i]--; sum++; } minx = arr[0]; for (int i = 1; i < n; i++) { if (minx > arr[i]) { minx = arr[i]; } } for (int i = 0; i < n; i++) { arr[i] -= minx; } int miny; for (int i = n-1; i >= 0; i--) { if (arr[i] == 0) { miny = i; break; } } for (int i = miny+1; i < n; i++) { arr[i]--; sum++; } for (int i = 0; i < n; i++) { if (i != miny) cout << arr[i]<<" "; else cout << n * minx + sum << " "; } }先从最后一个人分配的房间往后减并且记录人数,然后找出最小的一个数,所有房间都减去这个人数,从右往左第一个为0的房间就是一开始的房间,然后再从最后一个房间一直往前减到这个房间,把最终减的所有人数放回这个房间就得到了最初的结果
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll a[100010]; int main(){ int n, x; cin>>n>>x; x = x-1; for(int i = 0; i<n;i++) cin>>a[i]; ll minima = INT_MAX, p=-1; for(int i = 1;i<=n;i++){ int ii = (i+x) % n; if(a[ii]<=minima){ minima= a[ii]; p = ii; } } // cout<<minima<<" "<<p<<endl; if(x==p){ for(int i=0;i<n;i++) a[i]-=minima; a[x] = minima*n; }else{ bool flag = true; for(int i =1;i<n;i++){ int ii = (p+i)%n; a[ii] -= minima+flag; a[p] += minima+flag; if(ii == x) flag = false; } } for(int i =0;i<n;i++){ cout<<a[i]<<" "; } }
import java.util.*; /** * @description: 方法1:递归回溯 * @author: HP * @date: 2020-08-23 8:44 */ public class Main { static int n; static int x; private static int getPre (int index) { return index - 1 == 0 ? n : index - 1; } private static int getTheFirstMinIndex (long[] rooms, long min) { for (int i = x; ; i = getPre(i)) { if (rooms[i] == min) { return i; } } } public static void main(String[] args){ Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ n = scanner.nextInt(); x = scanner.nextInt(); long[] rooms = new long[n + 1]; for (int i = 1; i <= n; i ++) { rooms[i] = scanner.nextLong(); } long min = Integer.MAX_VALUE; List<Integer> mins = new ArrayList<>(); for (int i = 1; i <= n ; i ++) { if (rooms[i] < min) { min = rooms[i]; } } //方法1 找到许多最小的 , 一个个尝试,不行的话回溯 for (int i = 1; i <= n; i ++) { if (rooms[i] == min) { mins.add(i); } } //方法2 // MD 要是我能直接知道 x (包括x自己)之前第一个最小的就是真的起点的话, 就好了,没看出来,烦死 // mins.add(getTheFirstMinIndex(rooms, min)); for (int index : mins) { if (tryDo(index, rooms, min)) { for (int i = 1; i <= n ; i ++) { System.out.print(rooms[i] + " "); } } /** * 记得结束 */ return; } } } public static boolean doOperation (long[] rooms, int start, int end, long del) { for (int i = start; i <= end ; i ++) { rooms[i] += del; if (rooms[i] < 0) { doOperation(rooms, start, i, - del); return false; } } return true; } public static boolean doEqual (long[] rooms, int index, long del) { if (del < 0) { return false; } rooms[index] = del; return true; } public static boolean tryDo (int minIndex, long[] rooms, long min) { if (minIndex < x) { return doOperation(rooms, minIndex + 1, x, -min - 1) && doOperation(rooms, x + 1, n, -min) && doOperation(rooms, 1, minIndex - 1, - min) && doEqual(rooms, minIndex, (n - x + minIndex - 1) * min + (x - minIndex) * (min + 1) + rooms[minIndex]); } else { if (x == minIndex) { return doOperation(rooms, 1, n, - min) && doEqual(rooms, x, (n) * min); } else { return doOperation(rooms, minIndex + 1, n, -min - 1) && doOperation(rooms, 1, x, - min - 1) && doOperation(rooms, x + 1, minIndex - 1, - min) && doEqual(rooms, minIndex, (minIndex - x - 1) * min + (x + n - minIndex) * (min + 1) + rooms[minIndex]); } } } }
#include <bits/stdc++.h> using namespace std; typedef long long ll; // !!!不能用int,有些cases会溢出!!! int main() { int n, last; cin >> n >> last; vector<ll> nums(n); for(ll& i:nums){cin >> i;} last -= 1; //向量下标应该从0开始 ll min_val = *min_element(nums.begin(), nums.end()); for(ll& i:nums){i -= min_val;} ll count = min_val * nums.size(); while(nums[last] > 0) { --nums[last]; ++count; --last; if(last == -1){last = n - 1;} } nums[last] = count; for(auto& i:nums){cout << i << ' ';} return 0; }