Codeforces Round #557 (Div. 2) [based on Forethought Future Cup - Final Round] D. Chladni Figure

D. Chladni Figure 传送门

题意:

给你一个圆,圆上有n个点,编号为1,2,…,n;圆上有m条边,问你旋转 k ∈ [ 1 , n − 1 ] k\in[1,n-1] k[1,n1] 个单位,能不能与圆图形重合

解法

很容易想到 n*m的做法(枚举k),但是显然是会超时的,然后我看题解看不懂,再然后我就去问我的队友- - -无所不能的tls,果然,他一句话点醒了我。

题解上面说:旋转的k一定是n的因子,为什么呢?
举个例子:当n=4时,考虑 k=2和k=3两种情况,设a[i]代表点 i 的状态(上面连着的边)

  • 当k=2满足条件时,则a[1] = a[3], a[2] =a[4] ,画一个图片可以这样理解

    点 1 和点 2组成一个圈,(1,2)能够变为 (3,4), (3,4)恰好也能到达(1,2)

  • 当k=3满足条件时,则a[1]=a[4]=a[3]=a[2] ??? 这不是k=1该有的情况吗???显然k=3是不满足的
    按画图的话,就是(1,2,3)一团,剩下一个当个的点(4),很明显,会有问题。

按照上面所说,当k是n的因子的时候,才能恰好旋转 k 的单位。

因此枚举n的因子就行了,时间复杂度 O(n的因子数量*m)
很明显,n的因子不多,上述方法可行。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;

int main() {
	int n,m;
    cin>>n>>m;
    vector<vector<int> >v(n+1);
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a>b)swap(a,b);
        if(b-a==n-b+a)      //特别注意,因为这样首可以与尾重叠,因此首位都要加入,可以由第四组样例看出来
        {
            v[a].push_back(b-a);
            v[b].push_back(b-a);
        }
        else if(b-a<n-b+a)    //只在顺时针方向第一个点压入长度
            v[a].push_back(b-a);
        else
            v[b].push_back(n-b+a);
    }
    for(int i=1;i<=n;i++)
        sort(v[i].begin(),v[i].end());

    for(int k=1;k<n;k++)
    {
        if(n%k)continue;

        bool ok=true;
        for(int i=1;i<=n;i++)
            if(v[i]!=v[(i+k>n)?(i+k-n):(i+k)])		//我也觉得很神奇,vector重载了==,差不多是用memcmp比较的
                ok=false;

         if(ok)
            return printf("Yes\n"),0;
    }

    printf("No\n");
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值