Polya定理及例题

  • 概念

先讲Burnside定理:

百度百科的传送门:https://baike.baidu.com/item/burnside%E5%BC%95%E7%90%86/1505996

Polya定理及例题_第1张图片

 再放一个例题:

Polya定理及例题_第2张图片

 

 重点还是Polya定理

百度百科的传送门:https://baike.baidu.com/item/Polya/11020869

Polya定理及例题_第3张图片

Polya定理在Burnside定理的基础上增加了 翻转 得到更大的置换群

( )内表示的是 循环节

关于定理概念也可以看看这篇博客:https://blog.csdn.net/lyc1635566ty/article/details/52545355

 

  • poj1286

Necklace of Beads

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 9432   Accepted: 3887

Description

Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 24 ). If the repetitions that are produced by rotation around the center of the circular necklace or reflection to the axis of symmetry are all neglected, how many different forms of the necklace are there? 

 

Input

The input has several lines, and each line contains the input data n. 
-1 denotes the end of the input file. 

Output

The output should contain the output data: Number of different forms, in each line correspondent to the input data.

Sample Input

4
5
-1

Sample Output

21
39

题目大意:

输入n,得到由红,绿,蓝三种颜色珠子串成的长度为n的项链有多少种。

(输入为 -1 时结束程序)

【因为 项链是一个圈 是可以翻转旋转的 所以用Polya定理做】 

放代码

#include 
#include 
#include 
#include 
#include 
#define LL long long
using namespace std;
//Polya定理 置换群
LL gcd(LL a,LL b)//计算最大公约数
{
    if (b==0)
        return a;
    return gcd(b,a%b);
}
int main()
{
    LL t;
    while (~scanf("%lld",&t))
    {
        LL sum=0;
        if (t==-1)break;
        if (t==0)//特殊判断 输入0输出0
        {
            printf("0\n");
            continue;
        }
        for (int i=1;i<=t;++i)
        {
            LL tmp=gcd(t,i);
            sum+=(LL)(pow(3.0,tmp*1.0));//位置不变时 所有的点都有三种情况
        }
        if (t%2==1)//判断t的奇偶
            sum+=(t*pow(3.0,(t+1)/2));//奇数情况下 置换造成的情况数量相同
        else//偶数情况时
        {
            sum+=(LL)((t/2)*pow(3.0,(t+2)/2.0));//对角线对称翻转
            sum+=(LL)((t/2)*pow(3.0,t/2));//对边对称翻转
        }
       sum=sum/(2*t);
       printf("%lld\n",sum);
    }
    return 0;
}

 

  • poj2409

Let it Bead

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6487   Accepted: 4339

Description

"Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you can deduce from the company name, their business is beads. Their PR department found out that customers are interested in buying colored bracelets. However, over 90 percent of the target audience insists that the bracelets be unique. (Just imagine what happened if two women showed up at the same party wearing identical bracelets!) It's a good thing that bracelets can have different lengths and need not be made of beads of one color. Help the boss estimating maximum profit by calculating how many different bracelets can be produced. 

A bracelet is a ring-like sequence of s beads each of which can have one of c distinct colors. The ring is closed, i.e. has no beginning or end, and has no direction. Assume an unlimited supply of beads of each color. For different values of s and c, calculate the number of different bracelets that can be made.

Input

Every line of the input file defines a test case and contains two integers: the number of available colors c followed by the length of the bracelets s. Input is terminated by c=s=0. Otherwise, both are positive, and, due to technical difficulties in the bracelet-fabrication-machine, cs<=32, i.e. their product does not exceed 32.

Output

For each test case output on a single line the number of unique bracelets. The figure below shows the 8 different bracelets that can be made with 2 colors and 5 beads.

Sample Input

1 1
2 1
2 2
5 1
2 5
2 6
6 2
0 0

Sample Output

1
2
3
5
8
13
21

题目大意:

每一行输入 e 和 s 求出 能由 e 种不同颜色的珠子串成的长度为 s 的手镯有多少种。

输入e=0且s=0时 结束程序

【注解中解释了gcd函数的作用】

放代码

#include 
#include 
#include 
#include 
#include 
#define  LL long long
using namespace std;
//Polya定理

LL gcd(LL a,LL b)//最大公约数 greatest common divisor
{
    if (b==0)return a;
    return gcd(b,a%b);
}
//考虑旋转:枚举旋转角度360/n*i,(0 t*i%n=0 => t=LCM(i,n)/i=n*i/GCD(n,i)/i=n/GCD(n,i)。
//那么可以上n/t种颜色,即n/(n/GCD(n,i))种,所以旋转的着色方案有k^GCD(n,i)种
int main()
{
    LL  n,q,k;
    while (~scanf("%lld%lld",&k,&n)&&k&&n)
    {
        LL ans=0;
        for (int i=1; i<=n; i++)
        {
            LL tmp=gcd(n,i);
            ans+=(LL)(pow(k,tmp*1.0));//位置不变时 所有的点都有k种情况
        }
        if (n%2==1)//判断t的奇偶
            ans+=(LL)(n*pow(k,(n+1)/2));//奇数情况下 置换造成的情况数量相同
        else//偶数情况时
        {
            ans+=(LL)((n/2)*pow(k,(n+2)/2.0));//对角线对称翻转
            ans+=(LL)((n/2)*pow(k,n/2));//对边对称翻转
        }
        ans=ans/(2*n);
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • poj2154

Color

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 11725   Accepted: 3775

Description

Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the necklace can be produced. You should know that the necklace might not use up all the N colors, and the repetitions that are produced by rotation around the center of the circular necklace are all neglected. 

You only need to output the answer module a given number P. 

Input

The first line of the input is an integer X (X <= 3500) representing the number of test cases. The following X lines each contains two numbers N and P (1 <= N <= 1000000000, 1 <= P <= 30000), representing a test case.

Output

For each test case, output one line containing the answer.

Sample Input

5
1 30000
2 30000
3 30000
4 30000
5 30000

Sample Output

1
3
11
70
629

题目大意:

第一行给出 X 之后输入X组 N 和 P

求出 至多用N种(可以少于N) 考虑旋转 不考虑翻转 构成长度为 P 的项链的数量

【只有旋转 则用Burnside定理】

PS:因为数据太大 不能用gcd函数实现 所以用欧拉函数优化

借鉴了别人的博客...因为第一次写的时候没有优化 连样例都过不去

参考:https://www.cnblogs.com/DrunBee/archive/2012/09/10/2678819.html

           https://blog.csdn.net/wsniyufang/article/details/6671122

放代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
//Polya定理 欧拉函数优化
//题目数据太大 不能用gcd
const int MAXN=1000000000;
int isprime[50001];
int prime[8001];
int num,n,p;
void getprime()//得到素数
{
    num=0;
    for(int i=2; i<=50000; i++)
        if(!isprime[i])
        {
            prime[num++]=i;
            for(int j=1; j*i<=50000; j++)
            {
                isprime[i*j]=1;
            }
        }
}
int euler(int x)//获得比n小的且与n互质的数的数目
{
    int res=x;
    for(int i=0; i1) res=res/x*(x-1);
    return res;
}
int expmod(int a,int b,int mod)//每次做幂级数运算都要取模操作
{
    int ret=1;
    a=a%mod;
    while(b>0)
    {
        if(b%2==1)
            ret=(ret*a)%mod;
        a=(a*a)%mod;//二分思想
        b=b/2;
    }
    return ret;
}

int main()
{
    int Case;
    getprime();
    scanf("%d",&Case);
    while(Case--)
    {
        scanf("%d%d",&n,&p);
        int ans=0,i;
        for(i=1; i*i

以后如果做到此类题目 还会来更新的......

你可能感兴趣的:(数学题)