码迷,mamicode.com
首页 > 其他好文 > 详细

polya定理小结

时间:2015-06-13 21:26:14      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题。

当项链旋转时有n种置换,循环节的个数分别是gcd(n, i);

当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个数是n/2+1

当项链珠子数是偶数个时,当翻转线穿过珠子时,循环节个数为n/2+1,否则为n/2;

1.poj 1286:

题目大意:用三种颜色对珠子数不超过24的项链染色,问有多少种染色情况。

这道题是最基本的polya定理考察,只要带入公式即可

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const long long maxa = 30;
long long edge[maxa];
void rotate(long long n, long long ii){
    for(long long i = 0; i < n; i++){
        edge[(i+ii)%n] = i;
    }
}
void turn(long long n, long long ii){
    for(long long i = n-1, j= 0; i >= 0; i--, j++){
        edge[(j+ ii)%n] = i;
    }
}
long long vis[maxa];
void dfs(long long i){
    if(vis[i] == 1)return ;
    vis[i] = 1;
    dfs(edge[i]);
}
int main(){
    int n, m;
    while(scanf("%d%d", &m, &n), n+m){
        if(n == 0){
            printf("0\n");
            continue;
        }
        long long ans = 0;
        for(long long i = 0; i < n; i++){
            rotate(n, i);
            long long o = 0;
            memset(vis, 0, sizeof(vis));
            for(long long k = 0;k  < n; k++){
                if(vis[k]==0){
                    o ++;
                    dfs(k);
                }
            }
            long long sum = 1;
            for(long long k = 0;k  < o; k++){
                sum *= m;
            }
            ans += sum;
        }
        for(long long i = 0; i < n; i++){
            turn(n, i);
            long long o = 0;
            memset(vis, 0, sizeof(vis));
            for(long long k = 0;k  < n; k++){
                if(vis[k]==0){
                    o ++;
                    dfs(k);
                }
            }
            long long sum = 1;
            for(long long k = 0;k  < o; k++){
                sum *= m;
            }
            ans += sum;
        }
        cout<<ans/n/2<<endl;
    }
}
View Code

2.poj 2409

题目大意,用c种颜色染n个珠子组成的项链,也是最基本的polya定理考察

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const long long maxa = 30;
long long edge[maxa];
void rotate(long long n, long long ii){
    for(long long i = 0; i < n; i++){
        edge[(i+ii)%n] = i;
    }
}
void turn(long long n, long long ii){
    for(long long i = n-1, j= 0; i >= 0; i--, j++){
        edge[(j+ ii)%n] = i;
    }
}
long long vis[maxa];
void dfs(long long i){
    if(vis[i] == 1)return ;
    vis[i] = 1;
    dfs(edge[i]);
}
int main(){
    int n, m;
    while(scanf("%d%d", &m, &n), n+m){
        if(n == 0){
            printf("0\n");
            continue;
        }
        long long ans = 0;
        for(long long i = 0; i < n; i++){
            rotate(n, i);
            long long o = 0;
            memset(vis, 0, sizeof(vis));
            for(long long k = 0;k  < n; k++){
                if(vis[k]==0){
                    o ++;
                    dfs(k);
                }
            }
            long long sum = 1;
            for(long long k = 0;k  < o; k++){
                sum *= m;
            }
            ans += sum;
        }
        for(long long i = 0; i < n; i++){
            turn(n, i);
            long long o = 0;
            memset(vis, 0, sizeof(vis));
            for(long long k = 0;k  < n; k++){
                if(vis[k]==0){
                    o ++;
                    dfs(k);
                }
            }
            long long sum = 1;
            for(long long k = 0;k  < o; k++){
                sum *= m;
            }
            ans += sum;
        }
        cout<<ans/n/2<<endl;
    }
}
View Code

3.hdu 1812

题目大意,用c种颜色对n*n的棋盘染色,有多少种方法

其实这道题就是可以看成一些(n+1)/2串项链,有八种置换,但是最坑的是大数怎么写都超时....万进制优化也超时.....打表还不让大那么大,java是很好的解决方法...谁爱写谁写....反正我不写啦啦啦啦

 

polya定理小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4574066.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!