zoukankan      html  css  js  c++  java
  • polya定理小结

    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
    ");
                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
    ");
                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是很好的解决方法...谁爱写谁写....反正我不写啦啦啦啦

    4.poj 2154

    题目大意,用n种颜色染长度是n的项链,结果mod p n<=10^9,p<= 30000,这里的项链只考虑旋转。

    常规解法是这样sum(n^gcd(n,i))%q,但是数据太大了不允许,我们知道的是n的因子数是可以通过搜索求出来的,那么如果gcd(n,i) == m,则i的数量显然是euler(i),需要注意的是最后除n的时候,n和p不一定互质所以需要在之前做处理,也就是将公式变成了sum(n^gcd(n,i)-1)%q,需要注意的是开long long会超时,所以在要用int,有些部分需要用同余模定理优化。

    #include<iostream>
    #include<string.h>
    #include<cmath>
    #include<stdio.h>
    using namespace std;
    const int maxa = 50;
    int app[maxa][2];
    int o;
    int ans;
    int n, q;
    int m;
    int euler(int n){ //返回euler(n)
         //if(n == 1)return 0;
         int res=n,a=n;
         for(int i=2;i*i<=a;i++){
             if(a%i==0){
                 res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
                 while(a%i==0) a/=i;
             }
         }
         if(a>1) res=res/a*(a-1);
         return res;
    }
    int kuick(int a, int b){
        int aa = 1;
        if(b == 0)return 1;
        aa = kuick(a, b/2);
        aa *= aa;
        aa%= q;
        if(b &1) aa*= a;
        aa %= q;
        return aa;
    }
    void dfs(int ii, int nn){//cout<<"*"<<ii<<" "<<o<<" "<<nn<<endl;
        if(ii == o){
            int aa = euler(n/nn) % q;
            ans += aa * kuick(n%q, nn-1);
            ans %= q;
            return;
        }
        dfs(ii+1, nn);
        int ss = 1;
        for(int i = 0; i < app[ii][1]; i++){
            ss *= app[ii][0];
            dfs(ii+1, ss*nn);
        }
    }
    int main(){
        cin>>m;
        while(m--){
            cin>>n>>q;
            int N = n;
            ans = 0;
            int sq = sqrt(n);
            o = 0;
            for(int i = 2;i  <= sq; i++){
                if(n % i == 0){
                    app[o][0] = i;
                    app[o][1] = 0;
                    while(n %i ==0){
                        app[o][1]++;
                        n /= i;
                    }
                    o++;
                }
            }
            //printf("*");
            if(n != 1){
                app[o][0] = n;
                app[o++][1] = 1;
            }
            n = N;
            dfs(0, 1);
            cout<<ans<<endl;
        }
    }
    View Code
  • 相关阅读:
    Developer 转型记:一个开发平台的“魔力”
    实践录丨如何在鲲鹏服务器OpenEuler操作系统中快速部署OpenGauss数据库
    一图看懂华为云DevCloud如何应对敏捷开发的测试挑战
    华为云GaussDB(DWS)内存知识点,你知道吗?
    在人工智能时代追逐的“后浪”
    【华为云技术分享】DLI跨源|当DLI遇见MongoDB
    授人以渔:stm32资料查询技巧
    云小课 | IPv4枯了,IPv6来了
    揭秘淘宝平台广告策略,拆解最佳投放实践
    520了,用32做个简单的小程序
  • 原文地址:https://www.cnblogs.com/icodefive/p/4574066.html
Copyright © 2011-2022 走看看