1 条题解
-
0
题目大意
有 个人围成一个圈,编号为 到 ,有 个活跃的位置 在每一分钟,活跃位置上的人会发生移动, 移动到 , 移动到 位置, 移动到 , 个移动同时发生。
接下来活跃位置会发生改变: 变成 , 变成 ,以此类推(如果 ,则 变为 )。请求出 分钟后每个人的位置。
思路
在样例解释中,观察一列中一个数字出现的次数和位置。
Initial, T = 0: order = [0 1 2 3 4 ], A = [0 2 3 ] T = 1: order = [3 1 0 2 4 ], A = [1 3 4 ] T = 2: order = [3 4 0 1 2 ], A = [2 4 0 ] T = 3: order = [2 4 3 1 0 ], A = [3 0 1 ] T = 4: order = [1 2 3 4 0 ], A = [4 1 2 ] T = 5: order = [1 0 2 4 3 ], A = [0 2 3 ] T = 6: order = [4 0 1 2 3 ], A = [1 3 4 ] T = 7: order = [4 3 1 0 2 ], A = [2 4 0 ] T = 8: order = [2 3 4 0 1 ], A = [3 0 1 ] T = 9: order = [0 2 4 3 1 ], A = [4 1 2 ] T = 10: order = [0 1 2 3 4 ], A = [0 2 3 ]我们发现其中 每过 秒就会后移 个位置,而 每一秒都会后移 个位置。
可以自己多测几组样例,发现一个规律:
如果我们把 和 的差表示为 。那么 和 之间所有数都是第一次走后每 秒向后移动 个数。
那么只需要把 中的每个数按这个规律算一次 秒后的位置,并存在一个新数组的对应位置。最后输出就行了。
所有疑问和细节均体现在代码,代码注释和解释中。
代码
#include<bits/stdc++.h> #define ll long long using namespace std; ll n,k,t; ll a[200005],ans[200005]; ll xs(ll x,ll y){//向上取整 return (x+y-1)/y; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>n>>k>>t; for(ll i=0;i<k;i++) cin>>a[i]; a[k]=n; for(ll i=0;i<k;i++){ ll x=a[i+1]-a[i];//x 表示每次停的时间和每次走的距离。 for(ll j=a[i];j<a[i+1];j++){ int p=xs(t-(j-a[i]),x)*x;//表示偏移量。 ll b=(j+p)%n;//用本身的值加上偏移量,注意 %n 保持在 0~n-1 范围内。 ans[b]=j;//记录答案。 } } for(int i=0;i<n;i++) cout<<ans[i]<<" "; return 0; }j-a[i]表示 第一次等多久才走。t-(j-a[i])表示 一共等的时间。xs(t-(j-a[i]),x)等的时间除以一次等 分钟,向上取整。表示等了几次,相当于走了几次。为什么要向上取整?请读者自己思考。xs(t-(j-a_{i}),x)*x走的次数乘每次走的距离,表示偏移量。
- 1
信息
- ID
- 6990
- 时间
- 4000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 10
- 已通过
- 4
- 上传者