我们把图中的pattern称作“模式”。
模式长度是 n,用 0-based 下标 i = 0 到 n - 1 表示第 i + 1 拍。第 i 拍会在 i + a_i 拍回到手中。我们记 f(i) = (i + a_i) % n。
我们可以发现,f 函数会形成很多循环。循环内里面的球只会在循环里(废话文学),所以只要统计每个循环里面哪个球会在哪个手。
如果 a_i 不全为偶数,那么那一定会换手了。
假如 n 是偶数,那么一个 i 是一定在一个手扔的。那么直接判断 i 奇偶。
n 是奇数的话答案应该根据有几次循环数量来看加多少。
// ILearnedSomeCoding 的万能头1.1
#include<iostream>
#include<vector>
#define code using
#define by namespace
#define ILearnedSomeCoding std
code by ILearnedSomeCoding;
#define ll long long
#define int64 long long
#define ull unsigned long long
#define uint64 unsigned long long
#define int128 __int128
#define uint128 __uint128_t
#define PQ priority_queue
#define fir(_S, _E, _T) for(int i = _S;i <= _E;i += _T)
#define fjr(_S, _E, _T) for(int j = _S;j <= _E;j += _T)
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
// cin >> t;
while(t--){
int n;
cin >> n;
vector<ll> a(n);
fir(0, n - 1, 1) cin >> a[i];
vector<int> f(n);
fir(0, n - 1, 1){
f[i] = ((i + (a[i] % n)) % n);
}
vector<char> vis(n, 0);
ll only1 = 0, only2 = 0, both = 0;
fir(0, n - 1, 1){
if(vis[i]) continue;
int u = i;
ll C = 0;
bool all_even = 1;
while(!vis[u]){
vis[u] = 1;
if(a[u] & 1) all_even = 0;
C += ((ll)u + a[u]) / n;
u = f[u];
}
if(C == 0)continue;
if(!all_even){
both += C;
}else{
if(!(n & 1)){
if(!(i & 1)) only1 += C;
else only2 += C;
}else{
ll hand1 = (C + (i & 1)) / 2;
only1 += hand1;
only2 += (C - hand1);
}
}
}
cout << only1 << " " << only2 << " " << both << "\n";
}
return 0;
}