HDU 5868 Different Circle Permutation(burnside 引理)

本文解析了HDU5868题目的解题思路,利用Burnside引理解决排列组合问题,探讨了不同圆排列的计数方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HDU 5868 Different Circle Permutation(burnside 引理)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5868

Description

You may not know this but it's a fact that Xinghai Square is Asia's largest city square. It is located in Dalian and, of course, a landmark of the city. It's an ideal place for outing any time of the year. And now:

There are N children from a nearby primary school flying kites with a teacher. When they have a rest at noon, part of them (maybe none) sit around the circle flower beds. The angle between any two of them relative to the center of the circle is always a multiple of 2π/N but always not 2π/N.

Now, the teacher raises a question: How many different ways there are to arrange students sitting around the flower beds according to the rule stated above. To simplify the problem, every student is seen as the same. And to make the answer looks not so great, the teacher adds another specification: two ways are considered the same if they coincide after rotating.

Input

There are T tests (T≤50). Each test contains one integer N. 1≤N≤1000000000 (10^9). Process till the end of input.

Output

For each test, output the answer mod 1000000007 (10^9+7) in one line.

Sample Input

4

7

10

Sample Output

3

5

15

题意:

有n个人假设完全一样,其中有一部分人坐成一个圆,这些人中任意两个人之间的距离是2π/N的倍数,但是不是2π/N。如果有两种坐法,一种通过旋转可以变成另外一种坐法,我们就可以认为这是一种坐法,问总共有多少种坐法?

题解:

题解参照https://async.icpc-camp.org/d/546-2016 先膜一发菊苣。

首先是不考虑旋转同构的情况下,我们自己手动推几个就可以得到一个公式就是f(n)=f(n-1)+f(n-2)。这里我们注意一点,就是当n=1的时候我们当其为1 。(具体原因我也不清楚)。

然后就是我们使用 burnside 引理(对于一个置换f,若一个着色方案s经过置换后不变,称s为f的不动点。将f的不动点数目记为C(f),则可以证明等价类数目为所有C(f)的平均值。此结论称为 burnside 引理————来自训练指南)。

下面则是求不动点数目。对于这个我们则是依次计算旋转1,2,……n的不动点数目。前面我们定义了f(n)为不考虑旋转同构的状态。下面就是将循环数代入即可,其中循环节的个数为gcd(i,n)。

当然直枚举每个点必然会超时。我们可以使用 (∑f(d)*φ(n/d))/n 代替。其中d是n的因子。

代码:

#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9+7 ;
struct matrix {
    long long x1,x2 ;
    long long x3,x4 ;
};

matrix mul(matrix a,matrix b){
    matrix ans ;
    ans.x1 = (a.x1*b.x1 + a.x2*b.x3)%mod ;
    ans.x2 = (a.x1*b.x2 + a.x2*b.x4)%mod ;
    ans.x3 = (a.x3*b.x1 + a.x4*b.x3)%mod ;
    ans.x4 = (a.x3*b.x2 + a.x4*b.x4)%mod ;
    return ans ;
}

long long quick_matrix(long long x){
    x -= 4 ;
    matrix ans,cal ;
    ans.x1 = ans.x2 = ans.x3 = 1 ; ans.x4 = 0 ;
    cal.x1 = cal.x2 = cal.x3 = 1 ; cal.x4 = 0 ;
    while (x){
        if (x%2)
            ans = mul(ans,cal) ;
        cal = mul(cal,cal) ;
        x >>= 1 ;
    }
    return (ans.x1*4+ans.x2*3)%mod ;
}

long long fx(long long x){
    if (x == 1)
        return 1;
    else if (x == 2)
        return 3;
    else if (x == 3)
        return 4;
    else return quick_matrix(x) ;
}

long long quick(long long a,long long n){
    long long ans = 1 ;
    long long cal = a ;
    while (n){
        if (n%2)
            ans = (ans*cal)%mod ;
        cal = (cal*cal)%mod;
        n >>= 1;
    }
    return ans ;
}

long long euler(long long n)
{
    long long ans = n;
    long long i;
    for (i = 2; i*i <= n; i++){
        if (n%i == 0){
            while (n%i == 0)
                n /= i;
            ans = ans/i*(i-1) ;
        } 
    }
    if (n != 1)
        ans = ans/n*(n-1);
    return ans;
}


long long solve(long long n){
    if (n == 1)
        return 2;
    long long ans = 0; 
    long long nn = n ;
    long long d;
    long long i;
    for (i = 1; i*i < n; i++){
        if (n%i == 0){
            ans = (ans + fx(i)*euler(nn/i) + fx(nn/i)*euler(i))%mod ; 
        } 
    }
    if (i*i == n)
        ans = (ans + fx(i)*euler(i))%mod ;
    return (ans*quick(nn,mod-2))%mod;
}

int main()
{
    long long n;
    while (~scanf("%lld",&n))
        printf("%lld\n",solve(n)) ;
    return 0 ;
}
posted @ 2016-09-12 00:28 Thecoollight 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/thecoollight/p/5863342.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值