luogu4980 Burnside引理和Polya定理学习笔记

我已经是一个啥都学不懂的人了

由于别人的博客都比较好,所以我就直接搬了一些了

1.置换。
大概学过抽象代数的同学都知道这个概念吧。
置换简单来说就是对元素进行重排列,如下图所示。置换是[1,n]到[1,n]的一一映射。

再比如,将正方形绕其中心逆时针旋转90度,可以看成是正方形四个顶点的一个置换。关于置换、置换群的具体理论,可以学一下抽象代数。
(1)置换可以分解成若干循环,方法为:连边 1 − > a 1 , 2 − > a 2 , … , i − > a i , … , n − > a n 1−>a1,2−>a2,…,i−>ai,…,n−>an 1>a1,2>a2,i>ai,n>an,任取一个元素,顺着有向边走,直到回到出发点,即形成一个环,剩余元素也是这样。
(2)如果一个状态经过置换f后跟原来相同,即 S [ 1 ] = S [ a 1 ] , S [ 2 ] = S [ a 2 ] , … , S [ n ] = S [ a n ] S[1]=S[a1],S[2]=S[a2],…,S[n]=S[an] S[1]=S[a1],S[2]=S[a2],,S[n]=S[an]。则称该状态为f 的不动点。
(3)题目中常常出现“本质不同的方案数”,一般是指等价类的数目,题目定义一个等价关系,满足等价关系的元素属于同一等价类。等价关系通常是一个置换集合 F F F,如果一个置换能把其中一个方案映射到另一个方案,则二者是等价的。
那么,置换构成的群就是置换群,就是交换排列顺序而已。

那么这里介绍一个 B u r n s i d e Burnside Burnside引理

对于一个置换 f f f,若一个染色方案 s s s经过置换后不变,称 s s s f f f的不动点。将 f f f的不动点数目记为 C ( f ) C(f) C(f),则可以证明等价类数目为所有 C ( f ) C(f) C(f)的平均值。

换句话说,我们是要所有不同的段之间的对应位置相同(其实也就是形成一个轮换)

举个例子,比如说,对于一个 2 × 2 2\times 2 2×2的矩形,他有四种置换,分别是旋转90°,180°,270°和0°,而对于这四种,对于90°,他就相当于四个块(每90°一块)的对应位置是相同的,那就是我们有两种染法(因为每一块就一个矩形,而只有染和不染两种选择。)

那么同理 180°是4种,0°是16种,270°也是2种

那么最终的 a n s = 2 + 2 + 4 + 16 4 = 6 ans = \frac{2+2+4+16}{4} = 6 ans=42+2+4+16=6

那么6就是我们最后要求的答案了。

那么有一个例题 T73176 秘籍-反复迷宫
23333
具体可以去洛谷团队——硫代硫酸钠纠察大队 里面看题面

这个题的话就是一个 b u r n s i d e burnside burnside引理的好题。
考虑正方形,假设我们已经通过递推得到了图形含有的总边数 s u m sum sum,那么考虑四边形的置换存在四种,那么我们分情况讨论,首先是 90 ° 90° 90°,由于我们在用 b u r n s i d e burnside burnside的时候规定了每一个对应位置都是相等的,也就是说,我们这一段和剩下所有的段都相等,方案数就是 C n / 4 r / 4 C_{n/4}^{r/4} Cn/4r/4,相当于划分成完全相同的四份,然后从一份中选出来 r / 4 r/4 r/4(因为剩下都一样)。
这里需要注意的是,由于要是完全相同,所以 r r r要是 4 4 4的倍数,剩下的也是同理,这里就不多介绍。

六边形也是一样的道理

那么我们会发现,这些栗子的共性就是只有染色和不染色两种情况。

那如果有颜色该怎么办呢?

这时候就需要 P o l y a Polya Polya定理

luogu4980 Burnside引理和Polya定理学习笔记_第1张图片
考虑每一个循环本身的颜色要求相同,但是互相之间却没有要求
比如说 6 个 数 组 成 的 环 6个数组成的环 6,那么可以构成 ( 1 , 4 ) ( 2 , 5 ) ( 3 , 6 ) (1,4)(2,5)(3,6) (1,4)(2,5)(3,6)这样的循环,两两之间没有限制的,那么我们会发现,实际上贡献就是 m k m^k mk,m是颜色数,k是这样的循环数。

回到洛谷4980这个题的话,我们经过推理(目前我所理解的最好理解的版本)
可以看出来,那么对于一个置换他的段数就是 n / ( l c m ( n , i ) / i ) n/(lcm(n,i)/i) n/(lcm(n,i)/i),原因同上。

那么也就是 g c d ( i , n ) gcd(i,n) gcd(i,n)

那么问题就转化成了求 ∑ i = 1 n n g c d ( i , n ) \sum_{i=1}^n n ^{gcd(i,n)} i=1nngcd(i,n)
推一波柿子
a n s = ∑ d ∣ n n d ∑ i = 1 n [ g c d ( i , n ) = = d ] ans = \sum_{d|n} n^d \sum_{i=1}^n[gcd(i,n)==d] ans=dnndi=1n[gcd(i,n)==d]
a n s = ∑ d ∣ n n d ∑ i = 1 n d [ g c d ( i , n d ) = = 1 ] ans =\sum_{d|n} n^d \sum_{i=1}^{\frac{n}{d}}[gcd(i,\frac{n}{d})==1] ans=dnndi=1dn[gcd(i,dn)==1]
a n s = ∑ d ∣ n n d × ϕ ( n d ) ans = \sum_{d|n} n ^d \times \phi(\frac{n}{d}) ans=dnnd×ϕ(dn)

那么我们可以对于每一个因数都是用 O ( n ) O(\sqrt n) O(n )的时间复杂度求出来 p h i phi phi

然后就可以解决这个题了

// luogu-judger-enable-o2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define pb push_back
#define mk make_pair
#define lson ch[x][0]
#define rson ch[x][1]
#define int long long

using namespace std;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

const int mod = 1e9+7;
 
int n,t;

int getphi(int x)
{
    if (x==1) return 1;
    int tmp = x;
    int xx = x;
    for (int i=2;i*i<=xx;i++)
    {
        if (x%i==0)
        {
            tmp=tmp/i*(i-1);
            while(x%i==0) x/=i;
        }
    }
    if (x>1) tmp=tmp/x*(x-1);
    return tmp;
}

int qsm(int i,int j)
{
    int ans=1;
    while (j)
    {
        if (j&1) ans=ans*i%mod;
        i=i*i%mod;
        j>>=1;
    }
    return ans;
}

signed main()
{
   t=read();

   while (t--)
   {
   	   n=read();
   	   int ans=0;
   	   for (int i=1;i*i<=n;i++)
   	   {
   	   	  if (n%i==0)
   	   	  {
   	   	  	 ans=(ans+qsm(n,i)*getphi(n/i)%mod)%mod;
   	   	  	 if (i*i!=n) ans=(ans+qsm(n,n/i)*getphi(i)%mod)%mod;
   	   	  }
       }
       cout<<ans*qsm(n,mod-2)%mod<<"\n";
   }
   return 0;
}

你可能感兴趣的:(polya,burnside,群论,数学+数论,c++)