• CF1147B Chladni Figure


    洛谷传送门 CF传送门

    题意

    给你一个 (n) 个点的图,其中有 (m) 条线段。求该图形是否为旋转对称图形。

    Solution

    我们设旋转 (x) 个点可以和原图形重合,那么 (kcdot x) 个点也可以

    反过来,已知旋转一圈就是原图形,此时旋转了 (n) 个点,我们只要找到一个 (n) 的因子满足旋转后和原图形重合即可。

    那么我们枚举 (n) 的因子和每一位旋转后的情况就好了

    判断时设此时枚举到 (d(d|n)) 和第 (i) 位,只要判断 (i,i+d) 所含的线段数量是否相等和每一条线段是否都对应。

    小剪枝:枚举每一位的过程中如果出现不相等的情况可以立即跳出,枚举 (n) 的因子的过程中如果出现满足答案的情况就立即跳出。

    注意:输入线段的两个端点 (u,v) 时,是有两条线段的,一条是 (v-u) ,一条是 (u-v+n) ,记得都储存

    Code

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=1e5+10;
    vector<int> d,p[N];
    int n,m,flag=1;
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n/2;i++)
            if(n%i==0) d.push_back(i);
        for(int i=1,u,v;i<=m;i++){
            scanf("%d%d",&u,&v);
            if(u>v) swap(u,v);
            p[u].push_back(v-u);
            p[v].push_back((n+u-v-1)%n+1);
        }
        for(int i=1;i<=n;i++)
            sort(p[i].begin(),p[i].end());
        for(int i=0;i<d.size();i++){
            flag=1;
            int now=d[i];
            for(int j=1;j<=n;j++){
                if(p[j].size()!=p[(j+now-1)%n+1].size()){
                    flag=0;
                    break;
                }
                for(int k=0;k<p[j].size();k++){
                    if(p[j][k]!=p[(j+now-1)%n+1][k]){
                        flag=0;
                        break;
                    }
                }
                if(flag==0) break;
            }
            if(flag==1) break;
        }
        if(flag==0) puts("No");
        else puts("Yes");
        return 0;
    }
    
  • 相关阅读:
    网络性能测试工具iperf详解
    linux下的抓包工具tshark和 tcpdump用法
    linux下网络发包工具
    >/dev/null 2>&1 的作用
    linux screen 命令详解
    wget 命令操作实例
    Centos Linux release 7.2.15ll (core) yum 安装java环境
    日志监听
    java 身份证工具类
    java 生成微信的二维码 工具类
  • 原文地址:https://www.cnblogs.com/jasony/p/13872576.html
Copyright © 2020-2023  润新知