HDU5868-Different Circle Permutation【Burnside】【欧拉函数】

在马大爷的指导下,再加上看了 http://blog.csdn.net/viphong/article/details/52540902# 的博客(ps:个人认为递推式证明有错),对于Burnside定理有了深入的了解。

Burnside定理 基本的叙述 参看 百度百科Burnside

尤其对于在应用中的例1,对于理解公式中各个参数的含义很有帮助

求出所有方案集合S,记为初始集合。

在S上有N(个数)种旋转方案,可以得到置换之后的Si,不动点的定义是,经过置换Ti后得到的Si中的某个方案和初始集合S中相对应的那个方案完全相同,那么这个点即为不动点。

Burnside引理的含义就是不动点的个数除以置换的个数,即平均每种置换有多少个不动点,就有多少个不同构的方案。

ans = ∑(每种置换中不动点的个数) / N;

①N种旋转(置换方式)有多少个不动点,经过置换Ti后不动,显然,对于所有的不动点都有一个共同性质具有长度为 gcd(i,n) 的循环节 

那么 方案数是多少呢,很显然就是长度为gcd(i,n)有多少种配色方案

又因为链是组成这题中环的一部分,所以除了黑黑不能相邻之外还要满足一个别的条件那就是首尾不能同为黑

②长度为x的环不考虑同构有多少种方案,动态规划?递推式? 有f[x] = f[x-1] + f[x-2]

显然有

f(2) = 3;(01,00,10)

f(3) = 4;(000,100,001,010)

推导过程讨论第x位放什么

若放白色(0为白,1为黑),F_w[x] = F_w[x-1] + F2[x-1]

说明F2的含义为,F2[t]是长度为t,格式为10XXX01(对L=x-1来说是非法方案,但是这些串加上一个0之后,对于L=x是合法)的链的个数

若放黑色,F_b[x] = F[x-2] - F3[x-2]

说明F3的含义为,F3[t]是长度为t,格式为10XXX0(对L = t 是合法的)的链的个数

显然观察F2和F3的定义,会发现F2[t] = F3[t-1]

==》 F[x] = F_w[x] + F_b[x] = F[x-1] + F[x-2];

欧拉函数优化这个过程。百度百科欧拉函数 

 根据上面讨论,公式变为∑ (F( gcd(i,N) )) / N   (1<=i<=n)

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 struct mat
 6 {
 7     long long a[4][4];
 8 };
 9 const long long mod=(1e9)+7;
10 mat operator *(mat A,mat B)
11 {
12     mat C;
13     memset(C.a,0,sizeof(C.a));
14     for (int i = 1 ; i<=2; i++)
15         for (int j = 1 ; j<=2 ; j++)
16             for (int k = 1; k<=2; k++)
17         C.a[i][j]= (C.a[i][j] + (A.a[i][k]*B.a[k][j]) % mod) % mod;
18     return C;
19 }
20 mat ksm(mat A,long long t)
21 {
22     mat ans;
23     memset(ans.a,0,sizeof ans.a);
24     ans.a[1][1] = 1;
25     ans.a[2][2] = 1;
26     while (t){
27         if (t&1) ans = ans*A;
28         A=A*A;
29         t/=2;
30     }
31     return ans;
32 }
33 long long  inv(long long A)
34 {
35     long long tans = 1;
36     long long t = mod-2LL;
37     while (t){
38         if (t&1LL) tans = (tans*A) % mod;
39         A=(A*A) % mod;
40         t/=2LL;
41     }
42     return tans;
43 }
44 long long  eula (long long x)
45 {
46     long long ans = x;
47     for (long long i = 2; i*i <=x; i++){
48         if (x%i==0){
49             ans = ans-ans/i;
50             while (x%i==0)x/=i;
51         }
52     }
53     if (x!=1) ans = ans - ans/x;
54     return ans;
55 }
56 long long F(long long i)
57 {
58     if (i==1) return 1;
59     if (i==2) return 3;
60     mat A;
61     memset(A.a,0,sizeof(A.a));
62     A.a[2][1] = 1;
63     A.a[2][2] = 1;
64     A.a[1][2] = 1;
65     A = ksm(A,i-2);
66     return (A.a[1][2] + 3*A.a[2][2] % mod ) % mod;
67 }
68 int main()
69 {
70     long long N = 0;
71     while (cin >> N ){
72         if (N==1) {puts("2");continue;}
73         long long sans = 0;
74         for (long long i = 1; i*i<=N; i++){
75             if (N % i==0){
76                 sans= (sans + F(i) * eula(N/i) % mod ) % mod;
77                 if (i*i!=N) sans= (sans + F(N/i) * eula(i) % mod ) % mod;
78             }
79         }
80         sans = ((sans * inv(N)) % mod);
81         cout << sans <<endl;
82     }
83     return 0;
84 }

 

 

 

 

posted @ 2017-04-11 19:59  HITLJR  阅读(316)  评论(0编辑  收藏  举报