鞍山2014Regional K


赛场上憾失金牌的题目

理论上最多旋转0/90/180/270这4个状态

我写了枚举1点转到哪里,2点转到哪里,然后通过旋转角度求

把eps设大一点精度问题就可以解决了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;

typedef long long LL;

const int mod = 1e9+7;

#define CLR(a,b) memset(a,b,sizeof(a))
const double eps=1e-4;
const double pi=acos(-1.0);
#define next(i) ((i+1)%n)
inline int cmp(double x) { //≈–∂œ ˝µƒ∑˚∫≈
    return x<-eps?-1:x>eps?1:0;
}
inline double sqr(double x) { //º∆À„ ˝µƒ∆Ω∑Ω
    return x*x;
}
struct point { //µ„¿‡
    double x,y;
    point() {}
    point(double a,double b):x(a),y(b) {}
    void input() {
        scanf("%lf%lf",&x,&y);
    }
    friend point operator+(const point &a,const point &b) {
        return point(a.x+b.x,a.y+b.y);
    }
    friend point operator-(const point &a,const point &b) {
        return point(a.x-b.x,a.y-b.y);
    }
    friend bool operator==(const point &a,const point &b) {
        return cmp(a.x-b.x)==0&&cmp(a.y-b.y)==0;
    }
    friend point operator*(const point &a,const double b) {
        return point(a.x*b,a.y*b);
    }
    friend point operator*(const double a,const point &b) {
        return point(a*b.x,a*b.y);
    }
    friend point operator/(const point &a,const double b) {
        return point(a.x/b,a.y/b);
    }
    double norm() {
        return sqrt(sqr(x)+sqr(y));
    }
};

double det(const point &a,const point &b) { //º∆À„œÚ¡ø≤ʪ˝
    return a.x*b.y-a.y*b.x;
}
double dot(const point &a,const point &b) { //º∆À„œÚ¡øµ„ª˝
    return a.x*b.x+a.y*b.y;
}
double dist(const point &a,const point &b) { //º∆À„¡Ωµ„懿Î
    return (a-b).norm();
}
point rotate_point(const point &p,double A) { //º∆À„œÚ¡øp»∆ƒÊ ±’Ζ˝◊™Aª°∂»µ√µΩµƒœÚ¡ø
    return point(p.x*cos(A)-p.y*sin(A),p.x*sin(A)+p.y*cos(A));
}

LL fpow(int n ,int k){
    LL ans = 1,base = n;
    while(k){
        if(k & 1)ans = ans * base % mod;
        base = base * base % mod;
        k >>= 1;
    }
    return ans;
}
const int N = 205;
int n,m,c,idx[N];;
point p[N],np[N];
bool go[N][N],vis[N];

int check()
{
    for(int i =1 ;i <= n ; i++){
        for(int j = 1; j <= n ; j++){
            if(go[i][j] && !go[idx[i]][idx[j]])return -1;
        }
    }
    CLR(vis, 0);
    int cnt = 0;
    for(int i = 1 ;i <= n ; i++){
        if(vis[i])continue;
        cnt ++;
        int nxt = idx[i];
        int start = i;
        vis[nxt] = 1;
        while(idx[nxt] != start){
            nxt = idx[nxt];
            vis[nxt] = 1;
        }
    }
    return fpow(c,cnt);
}

void solve()
{
    LL ans = 0;
    int G = 0;
    for(int i = 1 ;i <= n ; i ++){
        for(int j = 1 ; j <= n ; j++){
            if(i == j)continue;
            if((p[j]-p[i]).norm() != (p[2]-p[1]).norm())continue;
            double phi = asin(det(p[2]-p[1],p[j]-p[i])/(p[2]-p[1]).norm()/(p[j]-p[i]).norm());
            if(phi == 0){
                phi = acos(dot(p[2]-p[1],p[j]-p[i])/(p[2]-p[1]).norm()/(p[j]-p[i]).norm());
            }
            np[1] = p[i];
            np[2] = p[j];
            for(int k = 3; k <= n ; k++){
                np[k] = rotate_point((p[k]-p[1]),phi) + p[i];
            }
            bool ok = 1;
            CLR(idx,-1);
            idx[1] = i;
            idx[2] = j;
            for(int k = 3 ;k  <= n ; k ++){
                bool fid = 0;
                for(int l = 1 ; l <= n ; l ++){
                    if(np[k] == p[l]){
                        idx[k] = l;
                        fid = 1;
                        break;
                    }
                }
                if(!fid)ok = 0;
            }
            if(!ok)continue;
            int ret = check();
            if(ret == -1)continue;
            else {(ans += ret) %= mod;G++;}
        }
    }
    printf("%lld\n",ans*fpow(G,mod-2)%mod);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&c);
        for(int i = 1; i <= n ; i++){
            p[i].input();
        }
        for(int i = n+1 ; i<= 2 * n ;i ++){
            p[i] = p[i-n];
        }
        CLR(go,0);
        for(int i = 0 ; i < m ; i ++){
            int a,b;
            scanf("%d%d",&a,&b);
            go[a][b] = go[b][a] = 1;
        }
        solve();
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值