POJ 2888 Magic Bracelet(burnside引理+矩阵)

题意:一个长度为n的项链,m种颜色染色每个珠子。一些限制给出有些颜色珠子不能相邻。旋转后相同视为相同。有多少种不同的项链?

思路:这题有点综合,首先,我们对于每个n的因数i,都考虑这个因数i下的不变置换个数,然后乘以(n/i)的欧拉函数加到ans上面,然后再让ans乘以n在模p下的逆元。至于怎么求因数i下的不变置换个数,相信大家都做过没有限制的,至于有限制的,大家可以考虑一下这样:初始数组a[m][m]都为1,对于每个限制x,y,都令a[x][y]=a[y][x]=0,我们有一个数列:b1,b2,b3,b4...bm,那么对于每个i∈[1,m-1],都有a[bi][bi+1]=1,这样想到了什么?就是矩阵乘法,对于刚刚的矩阵a我们让s=a^i,然后把每个a[i][i]加起来,这样就代表:每个i出发又回到i的方法数,这样就变成因数i下的不变置换个数了!

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 const int Mod=9973;
  7 int a[105][105],b[105][105],c[105][105],s[105][105],n,m,K;
  8 int read(){
  9     char ch=getchar();
 10     int t=0,f=1;
 11     while (ch<‘0‘||ch>‘9‘){
 12         if (ch==‘-‘) f=-1;
 13         ch=getchar();
 14     }
 15     while (‘0‘<=ch&&ch<=‘9‘){
 16         t=t*10+ch-‘0‘;
 17         ch=getchar();
 18     }
 19     return t*f;
 20 }
 21 void exgcd(int a,int b,int &x,int &y){
 22     if (b==0){
 23         x=1;
 24         y=0;
 25         return;
 26     }
 27     exgcd(b,a%b,x,y);
 28     int t=x;
 29     x=y;
 30     y=(t-a/b*y);
 31 }
 32 int inv(int n){
 33     int A,B,x,y;
 34     A=n;B=Mod;
 35     exgcd(A,B,x,y);
 36     return (x+Mod)%Mod;
 37 }
 38 int euler(int n){
 39     int res=n,a=n;
 40     for (int i=2;i*i<=n;i++)
 41         if (a%i==0){
 42             res=res/i*(i-1);
 43             while (a%i==0) a/=i;
 44         }
 45     if (a>1) res=res/a*(a-1);
 46     return res%Mod;
 47 }
 48 void mult_matrix1(){
 49     for (int i=1;i<=m;i++)
 50      for (int j=1;j<=m;j++)
 51       c[i][j]=0;
 52     for (int i=1;i<=m;i++)
 53      for (int j=1;j<=m;j++)
 54       for (int k=1;k<=m;k++)
 55        c[i][j]=(c[i][j]+s[i][k]*b[k][j])%Mod;
 56     for (int i=1;i<=m;i++)
 57      for (int j=1;j<=m;j++)
 58        s[i][j]=c[i][j];
 59 }
 60 void mult_matrix2(){
 61     for (int i=1;i<=m;i++)
 62      for (int j=1;j<=m;j++)
 63       c[i][j]=0;
 64     for (int i=1;i<=m;i++)
 65      for (int j=1;j<=m;j++)
 66       for (int k=1;k<=m;k++)
 67        c[i][j]=(c[i][j]+b[i][k]*b[k][j])%Mod;
 68     for (int i=1;i<=m;i++)
 69      for (int j=1;j<=m;j++)
 70        b[i][j]=c[i][j];
 71 }
 72 int work(int x){
 73     for (int i=1;i<=m;i++)
 74      for (int j=1;j<=m;j++)
 75       b[i][j]=a[i][j],s[i][j]=0;
 76     int ans=0;
 77     for (int i=1;i<=m;i++)
 78       s[i][i]=1;
 79     while (x){
 80         if (x%2) mult_matrix1();
 81         mult_matrix2();
 82         x/=2;
 83     }
 84     for (int i=1;i<=m;i++) ans=(ans+s[i][i])%Mod;
 85     return ans;
 86 }
 87 int main(){
 88     int T=read();
 89     while (T--){
 90        n=read();m=read();K=read();
 91        for (int i=1;i<=m;i++)
 92          for (int j=1;j<=m;j++)
 93            a[i][j]=1;
 94        for (int i=1;i<=K;i++){
 95             int x=read(),y=read();
 96             a[x][y]=a[y][x]=0;
 97        }
 98        int ans=0;
 99        for (int i=1;i*i<=n;i++)
100         if (n%i==0){
101             ans=(ans+work(i)*euler(n/i))%Mod;
102             if (i*i!=n)
103             ans=(ans+work(n/i)*euler(i))%Mod;
104         }
105        ans=(ans*inv(n%Mod))%Mod;
106        printf("%d\n",ans);
107     }
108 }
时间: 2024-08-17 12:20:49

POJ 2888 Magic Bracelet(burnside引理+矩阵)的相关文章

poj 2888 Magic Bracelet(Polya+矩阵快速幂)

Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4990   Accepted: 1610 Description Ginny’s birthday is coming soon. Harry Potter is preparing a birthday present for his new girlfriend. The present is a magic bracelet which

【POJ2888】Magic Bracelet Burnside引理+欧拉函数+矩阵乘法

[POJ2888]Magic Bracelet 题意:一个长度为n的项链,有m种颜色的珠子,有k个限制(a,b)表示颜色为a的珠子和颜色为b的珠子不能相邻,求用m种珠子能串成的项链有多少种.如果一个项链在旋转后与另一个项链相同,则认为这两串珠子是相同的. $n\le 10^9,m\le 10,k\le \frac{m(m-1)} 2 $ 题解:好题. 依旧回顾从Burnside引理到Pólya定理的推导过程.一个置换中的不动点要满足它的所有循环中的点颜色都相同,那么在旋转i次的置换中,循环有gc

POJ2888 Magic Bracelet

Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 5476   Accepted: 1775 Description Ginny’s birthday is coming soon. Harry Potter is preparing a birthday present for his new girlfriend. The present is a magic bracelet which consists of n 

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加法下是一个群. 群元素的个数有限,称为有限群,且其中元素的个数称为

hdu 5868 2016 ACM/ICPC Asia Regional Dalian Online 1001 (burnside引理 polya定理)

Different Circle Permutation Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 208    Accepted Submission(s): 101 Problem Description You may not know this but it's a fact that Xinghai Square is

poj-2888 Magic Bracelet

题意: 给出n个珠子的项链和m种珠子: 珠子之间有k对关系,这些珠子不能相邻: 无法通过旋转变成相同的项链视为本质不同: 求本质不同的项链个数,答案对9973取模: n<=10^9,gcd(n,9973)=1,m<=10: 题解: 这显然是一个置换计数的问题: 上burnside引理还是选择poi? 上burnside引理,因为poi定理对颜色的限制要很宽泛才行! 先考虑一种置换姿势,旋转x个珠子: 那么就将项链分成了gcd(x,n)大小的段,而要求的不变置换数要求这些段完全相同: 问题就是求

POJ 3624 Charm Bracelet

Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weightWi (1 ≤ Wi ≤

[再做01背包] POJ 3624 Charm Bracelet

接触动态规划的第一题是数塔问题,第二题就是01背包问题了. 当时看的懵懵懂懂,回过头来再看这道题还是非常简单的了. 用 dp[i][j] 表示取前i种物品,使它们总体积不超过j的最优取法取得的价值总和状态转移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j-cost[i]]+weight[i]) 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstri

bzoj1004: [HNOI2008]Cards Burnside引理+01背包

三维01背包算出在每一个置换下不变的染色方案数,Burnside引理计算答案. PS:数据太水所以只算恒等置换也是可以过的. #include<bits/stdc++.h> using namespace std; int n,m,p,x,y,z; bool u[61]; int f[21][21][21],s[61],v[61]; int power(int u,int v){ int d=1; for(;v;v>>=1){ if(v&1) d=d*u%p; u=u*u%