我是靠谱客的博主 傲娇野狼,最近开发中收集的这篇文章主要介绍【Polay定理总结】【2019华为笔试】【普通涂色问题 组合数学】召唤师的技能——圆排列,翻转和项链排列题目描述:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目描述:

华为用的这个, 其实是个杭电的题目:
题目链接:hdu 3923 Invoker
dota游戏里面,召唤师可以控制冰雷火三种元素,并通过元素组合产生新的技能。现在我们修改了张新的地图, 地图中他能够控制n种元素, 并且将m个元素围成一个圈组成一 个新技能(这m个元素通过旋转或反转,算作重复,如123、231、312、 321、213、 132都算重复),那么召唤师能组合多少技能(20000>=n>=1 ,1<=m<=10000),由于结果可能很大,请将结果对1000000007取余

  1. 先从n个不同元素里面选择m个元素,得到选择的种类数,
  2. 用n个元素去填满m个空位槽,填法通过旋转或者翻转,都算作重复

假设m是3,那么,可以旋转0度,120度,240度
旋转0度: ( 1 2 3 1 2 3 ) begin{pmatrix} 1 & 2 &3 \ 1 & 2&3end{pmatrix} (112233),循环节3
旋转120度: ( 1 2 3 3 2 1 ) begin{pmatrix} 1 & 2 &3 \ 3&2&1end{pmatrix} (132231),循环节2,
旋转240度: ( 1 2 3 2 3 1 ) begin{pmatrix} 1 & 2 &3 \ 2 & 3&1end{pmatrix} (122331),循环节1
可以看作用m个元素去填满n个空位,
其实它这里没有说的很清楚,112,322,133 这种包含了相同元素的组合也是可以的,困扰了我非常久,我觉得还是看珠子涂色问题比较清楚
杭电的题目里面详细解释了用例

For Case #1: we assume a,b,c are the 3 kinds of elements.
Here are the 21 different arrangements to invoke the skills
/ aaaa / aaab / aaac / aabb / aabc / aacc / abab /
/ abac / abbb / abbc / abcb / abcc / acac / acbc /
/ accc / bbbb / bbbc / bbcc / bcbc / bccc / cccc /

Output: 输出组合的技能数。

Sample Input
3 4
1 2

Sample Output
Case #1: 21
Case #2: 1

答案来源:https://cloud.tencent.com/developer/article/1179882
不使用欧拉质数表进行优化的话,会直接TimeOut,
而且面对大数时,有符号数溢出,会直接变成负数,

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MOD 1000000007
#define LL long long
using namespace std;
/***************************************************/
static int prime[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101
};
int cnt = 25;
//欧拉公式
LL Eular(LL num)
{
LL ret = 1;
for (int i = 0; i < cnt && prime[i] <= num; i++)
if (num % prime[i] == 0) {
ret *= (prime[i] - 1);
num /= prime[i];
while (num % prime[i] == 0) {
num /= prime[i];
ret *= prime[i];
}
}
if (num > 1)
ret *= (num - 1);
return ret % MOD;
}
//求指数
LL Pow(LL a, LL b) {
LL ret = 1;
while (b) {
if (b & 1)
ret = (ret * a) % MOD;
a = (a * a) % MOD;
b >>= 1;
}
return ret;
}
//Polya公式
LL Polya(int m, int n) {
LL sum = 0, i;
for (i = 1; i * i < n; i++) {
if (n % i == 0) {
sum = (sum + Eular(i) * Pow(m, n / i)) % MOD;
sum = (sum + Eular(n / i) * Pow(m, i)) % MOD;
}
}
if (i * i == n)
sum = (sum + Eular(i) * Pow(m, i)) % MOD;
if (n & 1)
sum = (sum + n * Pow(m, n / 2 + 1)) % MOD;
else
sum = (sum + n / 2 * (Pow(m, n / 2) + Pow(m, n / 2 + 1))) % MOD;
return (sum * Pow(2 * n, MOD - 2)) % MOD;
}
/***************************Polya end****************************/
int main()
{
LL m, n;
LL t, cas = 0;
scanf("%I64d", &t);
while (t--) {
scanf("%I64d%I64d", &m, &n);
//直接调用公式求解
printf("Case #%I64d: %I64dn", ++cas, Polya(m, n));
}
return 0;
}

解析:

使用Polay定理即可,详情看下面解析:

Polya定理:

设有n个对象,G是这n个对象上的置换群,用m种颜色涂染这n个对象,每个对象涂染一种颜色。若一种染色方案在群G的作用下变为另一种方案,则这两种方案当作是一种方案。那么存在的方案个数为 L L L,根据公式:
在这里插入图片描述
c(ai)是置换ai的循环节数。
m c ( a i ) = c 1 ( p i ) m^{c(ai)} = c1(pi) mc(ai)=c1(pi)

用一个样例来说明下面的4个概念:

  1. 置换群G
  2. 置换Gi的不动点个数(循环节为1的点数): c 1 ( p i ) c1(pi) c1(pi)
  3. 循环节: c ( a i ) c(ai) c(ai)
  4. 着色方案数计算

典例0:对2*2的方阵用黑白两种颜色涂色,问能得到多少种不同的图像

对2*2的方阵用黑白两种颜色涂色,问能得到多少种不同的图像?经过旋转使之吻合的两种方案,算是同一种方案。

  1. 若一种染色方案在置换群G的作用下变为另一种方案:
    例如
    在这里插入图片描述
    正方形C3旋转180度,变成正方形C5 ,说明在旋转180度这个置换下,C3和C5等价、
    可以知道对正方形而言,旋转的情况有,旋转90度,旋转180度,旋转270度,旋转0度, 所以置换群G为: 置 换 群 G = { 旋 转 90 度 , 旋 转 180 度 , 旋 转 270 度 , 旋 转 0 度 } 置换群G={旋转90度,旋转180度,旋转270度,旋转0度} G={901802700}

  2. c1(“旋转90度”)是置换旋转90度 的不动点的个数(既循环节为1的点数):
    例如:
    可知下面的16种情况中:
    在这里插入图片描述
    转90度时,正方形C3转90度可以得到C6的图形,C6转90度得到C5,以此类推,所以(把C6表示为6,C3表示为3)可以写出
    在这里插入图片描述
    可以看出:旋转90度时,3可以置换为6,6可以置换为5,5置换为4,4置换为3,回到了3,是一个循环。
    所以,把循环写在一起:(3,6,5,4)(1)(2)(8,7,10,9)(11,12)(13,16,15,14)
    不动点(循环里只有一个元素的集合),可以看出旋转90度的不动点是(1)、(2),
    同理
    转180度时,3可以置换为5,5可以置换为3,是一个循环,
    类似的,有(1)(2)(3,5)(4,6)(7,9)(8,10)(11)(12)(13,15)(16,14)
    所以正方形进行旋转180度的变换时,不动点为(1)(2)(11)(12)
    在这里插入图片描述
    所以,
    旋转0度有16个不动点,
    旋转90度有2个不动点,
    旋转180度有4个不动点,
    旋转270度有2个不动点,

  3. 循环节: c ( a i ) c(ai) c(ai)
    在这里插入图片描述
    方格可以 旋转 0° , 90 ° , 180 ° ,270° . 所以 群G = { 0° , 90 ° , 180 ° ,270° } , G的阶|G| = 4 ,
    可知
    G1置换{转0° } = ( 1 2 4 3 1 2 4 3 ) begin{pmatrix} 1 & 2 &4 &3 \ 1 & 2&4&3 end{pmatrix} (11224433)
    G2置换{转90° } = ( 1 2 4 3 3 1 2 4 ) begin{pmatrix} 1 & 2 &4 &3 \ 3 & 1&2&4 end{pmatrix} (13214234)
    G3置换{转180° } = ( 1 2 4 3 4 3 1 2 ) begin{pmatrix} 1 & 2 &4 &3 \ 4 & 3&1&2 end{pmatrix} (14234132)
    G4置换{转270° } = ( 1 2 4 3 2 4 3 1 ) begin{pmatrix} 1 & 2 &4 &3 \ 2 & 4&3&1 end{pmatrix} (12244331)
    所以G1置换(旋转0° )中,1旋转0° 后得到1,2旋转0° 得到2,3进行G1置换后(旋转0° )得到3,4置换后得到4,循环节为(1)(2)(3)(4),总共有4个

    G2置换(旋转90° )中,
    在这里插入图片描述
    位置1旋转90° 得到3,位置3旋转90° 得到4,4旋转90° 得到2,2旋转90° 得到1,回到了1,是一个循环。所以:G2置换(旋转90° )的循环节为(1,3,4,2)
    在这里插入图片描述在这里插入图片描述
    同理: G3置换(旋转180° )中,1旋转180° 后得到4,4旋转180° 得到1,是一个循环(1,4);
    2进行G3置换后(旋转180° )得到3,3置换后得到2,得到循环(2,3)
    循环节为(1,4)(2,3)
    在这里插入图片描述
    G1置换{转0° }的循环节是4个。 { (1),(2),(3),(4) }
    G2置换{转90° }的循环节是1, { (1,3,4,2) }
    G3置换{转180°}的循环节是2, { (1,4),(2,3) }
    G4置换{转270°}的循环节是1。 { (1,2,4,3) }

  4. 着色方案数量计算:
    在这里插入图片描述
    可知,|G| = 4(对应四种旋转角度)
    置换Gi的不动点个数(循环节为1的点数):
    c 1 ( p 1 : 0 ° ) = 16 , c1(p1:0°) = 16, c1(p1:0°)=16,
    c l ( p 2 : 90 ° ) = 2 , cl(p2:90°)= 2, cl(p290°)=2
    c l ( p 3 : 180 ° ) = 4 , cl(p3:180°)=4, cl(p3180°)=4
    c l ( p 4 : 270 ° ) = 2 cl(p4:270°)=2 cl(p4270°=2
    置换Gi的循环节个数:
    c ( p 1 : 0 ° ) = 4 , c(p1:0°) = 4, c(p1:0°)=4,
    c ( p 2 : 90 ° ) = 1 , c(p2:90°)= 1, c(p290°)=1
    c ( p 3 : 180 ° ) = 2 , c(p3:180°)=2, c(p3180°)=2
    c ( p 4 : 270 ° ) = 1 c(p4:270°)=1 c(p4270°=1

    所以
    L = 1 ∣ G ∣ ∗ [ 16 + 2 + 4 + 2 ] = 1 ∣ G ∣ ∗ [ 2 4 + 2 1 + 2 2 + 2 1 ] = 6 L = frac{1}{|G|}* [16 + 2 + 4 + 2] = frac{1}{|G|} *[ 2^4 + 2^1 + 2^2 + 2^1 ] = 6 L=G1[16+2+4+2]=G1[24+21+22+21]=6

    得到最后方案数 6种。

可以看出,如果要计算 置换Gi的不动点个数(循环节为1的点数)会特别麻烦,所以最好直接通过知道置换Gi的循环节个数来进行计算比较好,那么,怎么求一个置换的循环节数?

  1. 方法一:把所有置换写出来,就能知道它们的循环节数了。
  2. 方法二:现成公式,对于旋转,有c(ai) = gcd(n,i),i为转动幅度,1~n,gcd是求最大公约数

典例1:用2种颜色去染排成一个环的6个棋子

典型题目:用2种颜色去染排成一个环的6个棋子,如果通过旋转得到则只算一种,一共有多少种染色方案?
典型的满足polya公式的条件,m=2,n=6。因为是旋转得到的置换,所以存在6个置换(自己置换到自己也算)。

在这里插入图片描述
每个置换的循环节已经标出了。
所以根据polya定理公式可以算出,染色方案数为 ( 2 6 + 2 1 + 2 2 + 2 3 + 2 2 + 2 1 ) / 6 (2^6+2^1+2^2+2^3+2^2+2^1)/6 (26+21+22+23+22+21)/6 = 14

典例2:用m种颜色给n颗珠子染色,经过旋转和翻转的算同一

在这里插入图片描述

POJ2409:
题意:一家项链公司生产手镯。n颗珠子形成一个环,用m种颜色给n颗珠子染色,就得到了各种各样的手镯。但是,经过旋转翻转使之吻合的算同一种方案。例如,当用2种颜色对5颗珠子进行染色的方案数为8,
1.对于旋转:有c(gi) = gcd(n,i),i为转动几颗珠子。gcd是求最大公约数。
2. 对于翻转,当n为奇数时,c(gi) = (n/2)+1;当n为偶数时,n个置换里,有n/2个置换的循环节数为(n/2)+1,有n/2个置换的循环节数为n/2

所以,计算旋转得到的方案种类数,再计算翻转得到的方案种类数,最后除以(n*2)

计算a,b最大公约数

int gcd(int a, int b)
{
return b==0?a:gcd(b,a%b);
}

c++

#include <iostream>
#include <stack>
#include<string>
using namespace std;
typedef __int64 int64;
/***********
* 计算最大公约数
***********/
int gcd(int a, int b) {
return b == 0 ? a:gcd(b, a % b);
}
/*****
* 用m种颜色涂色均匀分布在圆环上的n颗珠子的方案数
******/
int64 polya_circle(double m, int n) {
if (n<0|| abs(m)<0.9999)
{
return 0;
}
int64 result = 0;
// 计算旋转方案数
for (int i = 1; i <=n; i++)
{
result += pow(m, gcd(n, i));
}
// 计算翻转方案数
if (n%2)
{
result += n * pow(m, (n / 2) + 1);
}
else {
result += (pow(m, n / 2) + pow(m, (n / 2) + 1)) * n / 2;
}
return result / n / 2;
}
void Test_polya(int64 result,int64 aim) {
if (result == aim)
{
cout << "pass" << endl;
}
else {
cout << "Failed" << endl;
}
}
void Test_polya_circle() {
Test_polya(polya_circle(2, 5), 8);
Test_polya(polya_circle(1, 1), 1);
Test_polya(polya_circle(5, 1), 5);
Test_polya(polya_circle(2, 6), 13);
Test_polya(polya_circle(6, 2), 21);
}
int main()
{
Test_polya_circle();
}

其他困难例题:

Kaleidoscope(HDU-6360)(Polya定理)
题目大意:给你一个菱形6面体(共60面),然后给你 n nn 种颜色给它每一个面上色,要求第 i ii 种颜色必须至少涂 c [ i ] c[i]c[i] 次,问你本质不同的方案数,旋转相同视作同一种方案,染色方案数对 p pp 取模,多组数据
数据范围:
在这里插入图片描述

参考:

https://blog.csdn.net/ojshilu/article/details/15378645
http://t.zoukankan.com/bhlsheji-p-4747427.html
https://www.iteye.com/blog/yzmduncan-1402942
https://blog.csdn.net/qq_37555704/article/details/88073792
https://blog.csdn.net/liangzhaoyang1/article/details/72639208

最后

以上就是傲娇野狼为你收集整理的【Polay定理总结】【2019华为笔试】【普通涂色问题 组合数学】召唤师的技能——圆排列,翻转和项链排列题目描述:的全部内容,希望文章能够帮你解决【Polay定理总结】【2019华为笔试】【普通涂色问题 组合数学】召唤师的技能——圆排列,翻转和项链排列题目描述:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部