【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]

【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]BirthdayToyTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):466    AcceptedSubmission(s):238ProblemDescriptionAekdyCoinloves

大家好,又见面了,我是你们的朋友全栈君。

Birthday Toy

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 466    Accepted Submission(s): 238




Problem Description
AekdyCoin loves toys. It is AekdyCoin’s Birthday today and he gets a special “Toy”.

The “Toy” is in bulk and AekdyCoin has to make one by him. Let’s assume that the “Toy” has N small white beads and one Big bead .If someone want to make a “Toy”, he (or she) must always puts the Big bead in center, and then connect the other N small beads around it by using N sticks with equal length, and then the N small beads must be connected by N sticks with equal length, and it could be seen as a regular polygon. Figure 1 shows a “Toy” with 8 small white beads and one big white bead.



【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]


Now AekdyCoin has C kinds of available color, say blue, green, yellow, pink …etc. He wants to color these beads, but he thinks that must be too boring and stupid. So he colors these beads with one role: any adjacent beads couldn’t have same color. Figure 2 shows a legal situation, and Figure 3 shows an illegal situation.



【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]




【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]


It seems that the “Toy” becomes more interesting for AekdyCoin right now; however, he wants to color the big bead in center. Of course, he should follow the role above.

Now AekdyCoin begins to play with the “Toy”, he always colors the big beads and then the other small beads. He should color under the rule above. After several minutes, AekdyCoin finally makes a perfect “Toy”. Figure 4 shows a situation that is under the color rule.



【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]


AekdyCoin now want to know the different method to color the “Toy” whit at most K color. (“Toy” contains N small beads and one big bead.)

But, no, the problem is not so easy .The repetitions that are produced by rotation around the center of the circular necklace are all neglected. Figure 5 shows 8 “Toy”, they are regard as one method.


【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]


Now AekdyCoin will give you N and K, he wants you to help him calculate the number of different methods, because the number of method is so huge, so AekdyCoin just want you to tell him the remainder when divided by M.

In this problem, M = 1,000,000,007.

 


Input
The input consists of several test cases.(at least 1000)

Every case has only two integers indicating N, K 

(3<=N<=10^9, 4<=K<=10^9)

 


Output
For each case, you should output a single line indicates the remainder of number of different methods after divided by M.
 


Sample Input
  
  
  
3 4 3 5 3 17 162 78923
 


Sample Output
  
  
  
8 40 19040 19469065
 


Source

题意:n个小圆组成的正n边形,中间有一个大圆。有木棍相连的两个圆不能有相同的颜色,旋转后相同视为相同的方案,求着色方案数。

【HDU2865】构造矩阵+Burnside定理+欧拉函数类似poj2888[通俗易懂]

设有n个小圆,k种颜色(3<=N<=10^9, 4<=K<=10^9)。

首先,很容易想到从k种选一种给大圆,然后用k-1种颜色对小圆着色。

若不存在相邻圆颜色不同这个限制,则直接Burnside定理。

若存在限制,但是颜色种数很少,可以构造矩阵然后快速幂,得到一个置换使着色不变的着色方案数。

现在颜色种数很多,但是颜色限制较简单,可以考虑公式之类的。

考虑将n个圆的环,等分成t部分,每部分有m个圆。F表示m个圆满足限制的着色方案数。

若m=1,则F=0

若m=2,则F=k*(k-1)

若m=3,则F=k*(k-1)*(k-2)

若m=4,则F=k*(k-1)*[(k-1)+(k-2)*(k-2)]

……

观察到F[n]=F[n-1]*(k-2)+F[n-2]*(k-1)。

那么就可以对该递推式构造矩阵快速幂得到每种分法的方案数。

剩下的同【POJ】2888 Magic Bracelet

#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <list>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-6
#define TRUE true
#define FALSE false
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 100005
#define mod 1000000007
const int MAXN = 2;
struct Matrix
{
    long long mat[MAXN][MAXN];
    void Zero()
    {
        memset(mat, 0, sizeof(mat));
    }
    void Unit()
    {
        memset(mat, 0, sizeof(mat));
        for (int i = 0; i < MAXN; i++)
            mat[i][i] = 1;
    }
    void Build(long long k)
    {
        Zero();
        mat[0][1] = 1;
        mat[0][0] = k - 2;
        mat[1][0] = k - 1;
    }
    void output()
    {
        for(int i=0;i<MAXN;i++)
        {
            for(int j=0;j<MAXN;j++)
            {
                printf("%d ", mat[i][j]);
            }
            printf("\n");
        }
    }
};

Matrix operator*(Matrix &a, Matrix &b)
{
    Matrix tmp;
    tmp.Zero();
    for (int k = 0; k < MAXN; k++)
    {
        for (int i = 0; i < MAXN; i++)
        {
            if (!a.mat[i][k])
                continue;
            for (int j = 0; j < MAXN; j++)
            {
                tmp.mat[i][j] += a.mat[i][k] * b.mat[k][j]%mod;
                if( tmp.mat[i][j]>=mod)
                    tmp.mat[i][j]-=mod;
            }

        }
    }
    return tmp;
}
Matrix operator ^(Matrix a, int k)
{
    Matrix tmp;
    tmp.Unit();
    for (; k; k >>= 1)
    {
        if (k & 1)
            tmp = tmp * a;
        a = a * a;
    }
    return tmp;
}
std::vector<int> prime;
const int  MAXPR = 320000;
bool vispr[MAXPR];
void Init()
{
    prime.clear();
    memset(vispr, 1, sizeof(vispr));
    int sqrtnum = (int)(sqrt((double)MAXPR) + EPS);
    for (int i = 2; i < sqrtnum; i++)
    {
        if (vispr[i])
            for (int j = i * i; j < MAXN; j += i)
                vispr[j] = false;
    }
    for (int i = 2; i < MAXPR; i++)
    {
        if (vispr[i])
            prime.push_back(i);
    }
}
LL Ext_gcd(LL a, LL b, LL &x, LL &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    LL ret = Ext_gcd(b, a % b, y, x);
    y -= a / b * x;
    return ret;
}
LL Inv(LL a, LL m)   ///求逆元a相对于m
{
    LL d, x, y, t = m;
    d = Ext_gcd(a, t, x, y);
    if (d == 1) return (x % t + t) % t;
    return -1;
}
//复杂度根号x
std::vector<int> factor;
void Factor(int n)
{
    factor.clear();
    int i;
    for (i = 1; i * i < n; i++)
    {
        if (n % i == 0)
        {
            factor.push_back(i);
            factor.push_back(n / i);
        }
    }
    if (i * i == n)
        factor.push_back(i);
}
long long F(int n, int k)
{
    long long res;
    if (n == 1)
        res = 0;
    else if (n == 2)
        res = (long long)k * (k - 1);
    else if (n == 3)
        res = (long long)k * (k - 1) % mod * (k - 2);
    else
    {
        Matrix g;
        g.Build(k);
        g = g ^ (n - 3);
        // g.output();
        res = g.mat[0][0] * k % mod * (k - 1) % mod * (k - 2);
        res += g.mat[1][0] * k % mod * (k - 1);
    }
    return (res) % mod;
}
int eular(int n)
{
    int i, res = 1;
    for (i = 2; i * i <= n; ++i)
    {
        if (n % i == 0)
        {
            n /= i; res *= i - 1;
            while (n % i == 0)
            {
                n /= i; res *= i;
            }
        }
    }
    if (n > 1)   res *= n - 1;
    return res;
}
int eularbyPR(int x)
{
    int res, i;
    res = x;
    for (i = 0; prime[i] * prime[i] <= x; i++)
    {
        if (x % prime[i] == 0)
        {
            res -= res / prime[i];
            while (x % prime[i] == 0)
                x /= prime[i];
        }
    }
    if (x > 1)
        res -= res / x;
    return res;
}
long long Burnside(int n, int k)
{
    long long ans=0;
    int i;
    Factor(n);
    for (i = 0; i < factor.size(); i++)
    {
        ans += F(factor[i], k) * eular(n / factor[i]) % mod;
         if (ans >= mod)
            ans -= mod;
    }
    return (ans * Inv(n, mod) + mod) % mod;
}
int main()
{
#ifdef DeBUGs
    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
    int n, k;
    Init();
    while (scanf("%d%d", &n, &k) + 1)
    {
        printf("%I64d\n", (Burnside(n, k - 1)*k + mod) % mod);
    }

    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163385.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月23日 下午7:16
下一篇 2022年7月23日 下午7:36


相关推荐

  • 企业微信如何制定社群sop

    企业微信如何制定社群sop什么是社群运营SOP?即标准作业程序。而社群运营SOP指的是社群运营工作的标准化,从拉新、促活到社群留存转化,都有一套标准的操作流程。社群运营工作有很多共性。企业制定社群运营SOP,将会大大提高工作效率,节省时间和人力成本。现在,越来越多企业通过企业微信进行社群运营。那么企业微信社群运营SOP应该如何制定呢?企业微信如何制定社群运营SOP?对于企业微信社群运营来说,做到定时定量,从而培养用户习惯是非常重要的。企业微信可以帮助企业员工进行客户群发、客户群群发,减少运营人员的工作量,用户一天仅可

    2022年5月26日
    40
  • 五种常用手机Java编程软件[通俗易懂]

    五种常用手机Java编程软件[通俗易懂]越来越多的朋友都对编程感兴趣,编程需要工具,所以大家也想知道有哪些好用的java编程工具,接下来系哦啊吧就为大家介绍几款常用的相关编程工具。1.JDKJDK-java开发工具包JDK是Java开发工具包,基本上每个研究java的人都首先在机器上安装JDK,那么他有哪些部件呢?下面是运行java时真正工作的四个文件夹:bin、include、lib、jrebin:是最重要的是编译器包括:java和jvm与头文件lib:类库jre:java运行时环境的交互一般用于java程序的开发,而jre只运行类而不编译

    2022年7月21日
    14
  • 【PLSQL】package包的使用

    【PLSQL】package包的使用

    2021年12月16日
    50
  • 案例:ELK日志分析系统

    案例:ELK日志分析系统通过对日志的分析 既可以未雨绸缪 预防故障的发生 又可以在故障发生时 寻找蛛丝马迹 快速定位故障点

    2026年3月17日
    2
  • GPGGA NTRIP RTCM 笔记

    GPGGA NTRIP RTCM 笔记NTRIP 通信过程 RTCM 解析

    2026年3月17日
    26
  • 学计算机我后悔了(计算机专业初级书籍)

    大家好,我是小林哥。平日里,大家都喊程序员加班多很辛苦,动不动就掉头发,但干的还是很香的,毕竟大多数公司钱还是给的很到位的,今年毕业应届生的我见到好多动不动就月薪20K~30K的,真让人两眼泪酸酸,当然这离不开他们大学期间的努力。讲真,没什么家庭背景的人,选择当程序员确实是比较好的选择了,原因有二:首先,当今互联网、AI人工智能、大数据等都是高速发展的行业,自然人才需求很多,薪资也相对其他传统行业高;第二,纯粹看你技术能力,只要自己愿意付出努力,技术能力肯定会慢慢提高上来,而且现在比起几十年

    2022年4月18日
    98

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号