首页 > 代码库 > hdu5080:几何+polya计数(鞍山区域赛K题)

hdu5080:几何+polya计数(鞍山区域赛K题)

/*

鞍山区域赛的K题。。当时比赛都没来得及看(反正看了也不会)

学了polya定理之后就赶紧跑来补这个题。。

由于几何比较烂写了又丑又长的代码,还debug了很久。。

比较感动的是竟然1Y了。。

*/

题目大意:

给定一些点,某些点上有边,问用k种颜色染色的等价类有多少种

思路:

由于坐标是整数。。只有可能旋转90,180,270才能得到置换

且图形必须为中心对称图形

先用几何方法找出对称中心

然后旋转,找是否出现置换。。。

由于点数只有50,几何预处理这一部分可以很暴力无脑的写。。各种判断相等即可

得到置换数和每个置换的循环数之后用polya定理的公式求和即可(取模需要逆元)

代码:

#include <iostream>#include <stdio.h>#include<string.h>#include<algorithm>#include<string>#include<math.h>#include<ctype.h>using namespace std;#define esp 0.0000000001#define mod 1000000007bool isequal(double a,double b){    if(fabs(a-b)<esp)        return 1;    return 0;}struct point{    double x,y;    bool operator ==(point a)    {        return (isequal(x,a.x)&&isequal(y,a.y));    }    void rotate(point o)    {        double y1=y-o.y;        double x1=x-o.x;        x=o.x+y1;        y=o.y-x1;    }}O,p[55],q[55];struct edge{    int a,b;    bool operator ==(edge t)    {        return ((p[a]==q[t.a]&&p[b]==q[t.b])||(p[b]==q[t.a]&&p[a]==q[t.b]));    }}e[2510];////int g,r[55],n,m,k,rev[5];long long exgcd(long long a,long long b,long long &x,long long &y){    if(a==0&&b==0) return -1;    if(b==0){x=1;y=0;return a;}    long long d=exgcd(b,a%b,y,x);    y-=a/b*x;    return d;}//*********求逆元素*******************//ax = 1(mod n)long long inv(long long a,long long n){    long long x,y;    long long d=exgcd(a,n,x,y);    if(d==1) return (x%n+n)%n;    else return -1;}long long quickmod(long long a,long long b,long long m) //a^b%m{    long long res=1;    while(b)    {        if(b&1)            res=res*a%mod;        b>>=1;        a=a*a%mod;    }    return res;}point mid(point a,point b){    point res;    res.x=(a.x+b.x)/2;    res.y=(a.y+b.y)/2;    return res;}point sym(point a,point o){    point res;    double x1=o.x-a.x;    double y1=o.y-a.y;    res.x=o.x+x1;    res.y=o.y+y1;    return res;}int yes(int i,int j){    int ok=1;    point tmp;    for(int i=0;i<n;i++)    {        tmp=sym(p[i],O);        int j;        for(j=0;j<n;j++)        {            if(p[j]==tmp)            {                break;            }        }        if(j==n)        {            ok=0;            break;        }    }    return ok;}int findo(){    int ok=0;    for(int i=0;i<n;i++)    {        for(int j=i+1;j<n;j++)        {            O=mid(p[i],p[j]);            if(yes(i,j))            {                ok=1;                break;            }        }        if(ok)            break;    }    return ok;}int check(){    int ok=1;    for(int i=0;i<m;i++)    {        int j;        for(j=0;j<m;j++)        {            if(e[j]==e[i])            {                break;            }        }        if(j==m)        {            ok=0;            break;        }    }    return ok;}int findrev(){    int ok=1;    for(int i=0;i<n;i++)    {        int j;        for(j=0;j<n;j++)        {            if(p[i]==q[j])            {                r[i]=j;                break;            }        }        if(j==n)            ok=0;        if(ok==0)            break;    }    return ok;}int findloop(){    int res=0;    bool vi[55];    memset(vi,0,sizeof(vi));    for(int i=0;i<n;i++)    {        if(!vi[i])        {            for(int j=i;;j=r[j])            {                vi[j]=1;                if(r[j]==i)                {                    break;                }            }            res++;        }    }    return res;}void reverse(){    rev[0]=n;    g=1;    if(!findo())    {        return;    }    memcpy(q,p,sizeof(q));    for(int i=1;i<=3;i++)    {        for(int j=0;j<n;j++)        {            q[j].rotate(O);        }        if(check())        {            if(findrev())                rev[g++]=findloop();        }    }}void ini(){    scanf("%d%d%d",&n,&m,&k);    for(int i=0;i<n;i++)    {        scanf("%lf%lf",&p[i].x,&p[i].y);    }    for(int i=0;i<m;i++)    {        scanf("%d%d",&e[i].a,&e[i].b);        e[i].a--;        e[i].b--;    }}void solve(){    reverse();    long long ans=0;    for(int i=0;i<g;i++)    {        ans+=quickmod(k,rev[i],mod);        ans%=mod;    }    if(g==4)    {        ans*=inv(2,mod);        ans%=mod;        ans*=inv(2,mod);        ans%=mod;    }    else    {        ans*=inv(g,mod);        ans%=mod;    }    printf("%I64d\n",ans);}int main(){    //freopen("in.txt","r",stdin);    int t;    scanf("%d",&t);    while(t--)    {        ini();        solve();    }    return 0;}

 

hdu5080:几何+polya计数(鞍山区域赛K题)