给定两个整数N和M , N表示圆周上的等距点, M表示由这些点形成的弦数。还给出了包含和弦位置的C 对向量。任务是将圆旋转任意度数,例如 X,其中 0 < X < 360,并检查 的弦是否仍然与原始圆对称。
例子:
Input: N = 12, M = 6, C = {{1, 3}, {3, 7}, {5, 7}, {7, 11}, {9, 11}, {11, 3}};
Output: YES
Input: N = 10, M = 3, C = {{1, 2}, {3, 2}, {7, 2}}
Output: NO
朴素方法:在范围 [1, N ] 中的每距离K 处旋转,并检查每个点 [a, b] 是否存在旋转点 [a + K , b + K ]。
如果存在任何 k 则打印 YES 否则打印 NO
时间复杂度:O(N*M)
有效的方法:检查 N 的除数就足够了。
让我们假设如果我们将图像旋转K 个单位,那么整个图像将被分成N/K个块。那么如果K不是 N的除数,就会有一个长度小于K的不对称块,并且图像永远不会与原始图形对称。
因此,计算N 的所有除数并检查每个和弦旋转和弦是否存在。
下面是上述方法的实现:
C++
// C++ Program to for the above approach
#include
using namespace std;
// Utility function to calculate
// divisors of a number in O(sqrt(N))
vector calculateDivisors(int N)
{
vector div;
for (int i = 1; i * i <= N; i++) {
if (N % i == 0) {
div.push_back(i);
if (N / i != i && i != 1) {
div.push_back(N / i);
}
}
}
return div;
}
int checkRotationallySymmetric(
vector > A,
int N, int M)
{
// Maintain a set to check quickly
// the presence of a chord
set > st;
for (int i = 0; i < M; i++) {
--A[i].first, --A[i].second;
if (A[i].first > A[i].second) {
swap(A[i].first, A[i].second);
}
st.insert(A[i]);
}
// Calculate the divisors of N.
vector div = calculateDivisors(N);
// Iterate through the divisors
for (auto x : div) {
bool exist = 1;
for (int i = 0; i < M; i++) {
int dx = (A[i].first + x) % N;
int dy = (A[i].second + x) % N;
if (dx > dy) {
swap(dx, dy);
}
if (st.find({ dx, dy }) != st.end()) {
// There exists a vaild
// chord after rotation
}
else {
// There is no valid chord after rotation
exist = false;
break;
}
}
// if there exist another chord after
// rotation for every other chord print
// YES and exit the function
if (exist) {
cout << "YES";
return 0;
}
}
cout << "NO";
return 0;
}
// Driver Code
int main()
{
int N = 12, M = 6;
vector > C
= { { 1, 3 }, { 3, 7 }, { 5, 7 },
{ 7, 11 }, { 9, 11 }, { 11, 3 } };
checkRotationallySymmetric(C, N, M);
return 0;
}
输出
YES
时间复杂度: O(M*sqrt(N)*log M)
空间复杂度: O(M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。