题目 | Cyperation
2023牛客暑期多校训练营7
G - Cyperation
https://ac.nowcoder.com/acm/contest/57361/G
题意
给定长度为
题解
特判全 YES
.
特判 NO
.(这种情况
对于给出的环
当且仅当所有小环能够有解时,原问题有解。
例如输入
接下来就要对每个小环求解了,由于已经进行了拆分,小环中每次操作相当于就是相邻两位一起
对于一个小环
变成了 经过上一步变成了 ,还要对 区间进行 次减操作才能置零。 经过上一步变成了 ,还要对 区间进行 次减操作才能置零。 经过上一步变成了 ,还要对 区间进行 次减操作才能置零。 经过上一步变成了 ,还要对 区间进行前面那个式子次减操作才能置零。
综上,如果假设了
为了方便起见,令
首先由于操作次数
另外别忘了还有
如果求出来 NO
.
对于
由于
若
直接检查就行,不符合则不成立输出 NO
.
若
首先检测是否有整数解(即
代码
代码中为方便取模下标从
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
bool check(vector<int> &a)
{
int n = a.size();
vector<int> p(n);
for (int i = 0; i < n; i++)
p[(i + 1) % n] = a[(i + 1) % n] - p[i];
bool op = false; // 1+ 0-
int l = 0, r = a.front();
for (int i = 1; i < n; i++)
{
if (op)
l = max(l, -p[i]);
else
r = min(r, p[i]);
if (l > r)
return false;
op ^= 1;
}
if (n & 1)
{
if (p.front() & 1)
return false;
int ans = p.front() / 2;
return l <= ans && ans <= r;
}
return p.front() == 0;
}
void solve()
{
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
bool all_zero = true;
for (int i = 0; i < n; i++)
{
if (a[i])
{
all_zero = false;
break;
}
}
if (all_zero)
{
cout << "YES" << endl;
return;
}
if (2 * k > n)
{
cout << "NO" << endl;
return;
}
vector<bool> vis(n + 10);
for (int i = 0; i < n; i++)
{
if (vis[i])
continue;
vector<int> ring;
int pos = i;
while (!vis[pos])
{
vis[pos] = true;
ring.push_back(a[pos]);
pos = (pos + k) % n;
}
if (!check(ring))
{
cout << "NO" << endl;
return;
}
}
cout << "YES" << endl;
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi
好!