hdu 5080 Colorful Toy(计算几何+polya定理)

题意:n个点m条边,给边染色,有c种颜色,求染色方案有几种(旋转重合的方案记作同一种);

思路:旋转染色方案数用polya定理解决,每个置换群计算一次;

由计算几何的方法控制旋转,由sin,cos的有理数性质得,分别计算旋转0,90,180,270的方案数;

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define db double
using namespace std;
const int N=55;
const db eps=1e-8;
const db PI=acos(-1.0);
const ll MOD=1000000007;
int n,m,mp[N][N];
bool mk[N];
ll c;
int sgn(db t){
  return t<-eps?-1:t>eps;
}
ll inv(ll t){   //inv
    ll res=1,k=MOD-2;
    while(k){
      if(k&1) res=(res*t)%MOD;
       t=(t*t)%MOD;
       k>>=1;
    }
    return res;
}
struct E{
  int a,b;
  void input(){
    scanf("%d%d",&a,&b);
  }
}ed[N*N];
struct P{
  db x,y;
  int id;
  void input(){
    int xx,yy;
    scanf("%d%d",&xx,&yy);
    x=xx,y=yy;
  }
  P(db xx=0,db yy=0):x(xx),y(yy){}
  P rot(db thta){ //坐标转化
      return P(x*cos(thta)-y*sin(thta),x*sin(thta)+y*cos(thta)); //不要忘记return!!!
  }
  P rotbyp(P center,db thta){ //绕中心旋转
     P tmp(x-center.x,y-center.y);
     P ans=tmp.rot(thta);
     ans=ans+center;
     return ans;
  }
  P operator + (const P &t)const{
      return P(x+t.x,y+t.y);
  }
  bool operator == (const P &t)const{
     return sgn(x-t.x)==0&&sgn(y-t.y)==0;
  }
}p[N],pb,np[N];
int pt[N];
ll g,ans;
bool check(){
  for(int i=0;i<m;i++){
    int a=ed[i].a,b=ed[i].b; //每条边的两端
    a=pt[a],b=pt[b];
    if(mp[a][b]&&mp[b][a]);  //是否连接
    else return false;
  }
  return true;
}
bool fl[N];
int find_t(){ //不同的等价类的个数,循环节数
  memset(fl,false,sizeof(fl));
  int res=0;
  for(int i=0;i<n;i++){
    if(!fl[i]){
       res++;
    }
    int t=i;
    while(!fl[t]){
        fl[t]=true;
        t=pt[t];
    }
  }
  return res;
}
void dfs(int v){
  if(v==n){ //波利亚计数
    if(check()){
      int t=find_t();
      g++;
      ll res=1;
      for(int i=0;i<t;i++) res=res*c%MOD;
      ans=(ans+res)%MOD;
    }
  }
  else{
      for(int i=0;i<n;i++){
        if(!mk[i]&&(np[v]==p[i])){ //重合点,找到最后一个重合位置
           mk[i]=true;
           pt[v]=i;
           dfs(v+1);
           mk[i]=false;
        }
      }
  }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%I64d",&n,&m,&c);
        pb.x=pb.y=0.0;
        for(int i=0;i<n;i++){
          p[i].input();
          p[i].id=i;
          pb.x+=p[i].x;pb.y+=p[i].y;
        }
        pb.x/=(db)n;pb.y/=(db)n; //中心
        memset(mp,0,sizeof(mp));
        for(int i=0;i<m;i++){
          ed[i].input();
          ed[i].a--;ed[i].b--;
          mp[ed[i].a][ed[i].b]=mp[ed[i].b][ed[i].a]=1;
        } //输入点和边
        ans=g=0;
        memset(mk,false,sizeof(mk));
        for(int i=0;i<4;i++){ //四个角度
          for(int j=0;j<n;j++){
            np[j]=p[j].rotbyp(pb,i*PI/2.0); //旋转后的点
          }
          dfs(0);
        }
        printf("%lld\n",ans*inv(g)%MOD);
    }
    return 0;
}
时间: 2024-12-14 07:41:24

hdu 5080 Colorful Toy(计算几何+polya定理)的相关文章

HDU 3923 Invoker 【裸Polya 定理】

参考了http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 的模板 对于每一种染色,都有一个等价群,例如旋转,翻转等.我们将每一种变换转换成一个置换群,通过置换群得到的都是等价的染色方案 最终我们要求的是非等价的染色方案数. 在Burnside定理中给出,在每一种置换群也就是等价群中的数量和除以置换群的数量,即非等价的着色数等于在置换群中的置换作用下保持不变的着色平均数. 我们以POJ 2409 Let i

hdu 1817 Necklace of Beads(Polya定理)

题目链接:hdu 1817 Necklace of Beads 这题的弱化版:传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef long long ll; 5 6 int t,n,m,cas; 7 8 ll mypow(ll a,ll k){ 9 ll an=1; 10 while(k){ 11 if(k&1)an=an*a

hdu 3547 (polya定理 + 小高精)

DIY CubeTime Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 207    Accepted Submission(s): 111 Problem Description Mr. D is interesting in combinatorial enumeration. Now he want to find out the numb

hdu 1817 Necklace of Beads(Polya定理)

Necklace of Beads Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 630    Accepted Submission(s): 232 Problem Description Beads of red, blue or green colors are connected together into a circular

HDU 1817Necklace of Beads(置换+Polya计数)

Necklace of Beads Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1817 Description Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 40 ). If

polya定理小结

polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题. 当项链旋转时有n种置换,循环节的个数分别是gcd(n, i); 当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个数是n/2+1 当项链珠子数是偶数个时,当翻转线穿过珠子时,循环节个数为n/2+1,否则为n/2; 1.poj 1286: 题目大意:用三种颜色对珠子数不超过24的项链染色,问有多少种染色情况. 这道题是最基本的polya定理考察,只要带入公式即可 #include<iostream> #incl

Polya定理,Burnside引理(转)

设G是一个集合,*是G上的二元运算,如果(G,*)满足下面的条件: 封闭性:对于任何a,b∈G,有a*b∈G; 结合律:对任何a,b,c∈G有(a*b)*c=a*(b*c); 单位元:存在e∈G,使得对所有的a∈G,都有a*e=e*a=a; 逆元:对于每个元素a∈G,存在x∈G,使得a*x=x*a=e,这个时候记x为a-1,称为a的逆元,那么则称(G,*)为一个群. 例:G={0,1,2,3,4....n-1}那么它在mod n加法下是一个群. 群元素的个数有限,称为有限群,且其中元素的个数称为

[BZOJ1004] [HNOI2008] Cards (Polya定理)

Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红色,Sb张蓝色,Sg张绝色.他又询问有多少种方案,Sun想了一下,又给出了正确答案. 最后小春发明了M种不同的洗牌法,这里他又问Sun有多少种不同的染色方案.两种染色方法相同当且仅当其中一种可以通过任意的洗牌法(即可以使用多种洗牌法,而每种方法可以使用多次)洗成另一种.Sun发现这个问题有点难度,决

BZOJ 1488 [HNOI2009]图的同构 Polya定理

题意:链接 **方法:**Polya定理 解析: 先扯点题外话. 小雨淅沥的下午,PoPoQQQ爷在屠了一道题后放松心情,恰看见我把知识点上的群论标记已会. 于是,为了发扬D人的精神,PoPoQQQ爷打开了BZOJ,给我找了这么一个题,说:"这题都没做过还敢说会群论?" -- -- 征战半下午,卒. (我好菜以后再也不敢说我会啥了T_T (做这道题千万别去OEIS找通项=-=) 好不扯了,言归正传说这道题怎么做. 这道题确实是个好题,跟以前的群论的解法有共同点但是又有新的东西. 反正我