• hdu 5868:Different Circle Permutation 【Polya计数】


    似乎是比较基础的一道用到polya定理的题,为了这道题扣了半天组合数学和数论。

    等价的题意:可以当成是给正n边形的顶点染色,旋转同构,两种颜色,假设是红蓝,相邻顶点不能同时为蓝。

    大概思路:在不考虑旋转同构的情况下,正n边形有fib(n+1)+fib(n-1)种染色方法(n==1特判),然后后面就是套公式了,涉及到要用欧拉定理优化,不然会T。(理论的东西看下组合数学书中polya计数部分,及数论书中欧拉函数部分中 n的约数的欧拉函数,感觉看博客不如系统的看看书,再结合一下网上一些比较基础的polya题来理解。)

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5868

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    LL Eular(LL n)
    {
        LL ret=n;
        for(LL i=2; i*i<= n; i++)
        {
            if(n%i==0)
            {
                ret-=ret/i;
                while(n%i==0) n/= i;
            }
        }
        if(n>1) ret-=ret/n;
        return ret;
    }
    LL qpow(LL n,LL k)
    {
        LL res=1;
        for(; k; k>>=1)
        {
            if(k&1) res=res*n%mod;
            n=n*n%mod;
        }
        return res;
    }
    LL inv(LL x)
    {
        return qpow(x,mod-2);
    }
    const LL N=2;
    struct Mat
    {
        LL mat[N][N];
    };
    Mat Mut(Mat a,Mat b)
    {
        LL i,j,k;
        Mat c;
        memset(c.mat,0,sizeof(c.mat));
        for(k=0; k<N; k++)
        {
            for(i=0; i<N; i++)
            {
                if(a.mat[i][k])
                    for(j=0; j<N; j++)
                    {
                        if(b.mat[k][j])
                            c.mat[i][j]=c.mat[i][j]+a.mat[i][k]*b.mat[k][j];
                        c.mat[i][j]=c.mat[i][j]%mod;
                    }
            }
        }
        return c;
    }
    Mat Pow(Mat a,LL n)
    {
        Mat c;
        for(int i = 0; i < N; ++i)
            for(int j = 0; j < N; ++j)
                c.mat[i][j] = (i == j);
        for(; n; n>>=1)
        {
            if(n&1)  c=Mut(c,a);
            a=Mut(a,a);
        }
        return c;
    }
    LL fib(LL x)
    {
        if(x==0) return 0;
        Mat A;
        A.mat[0][0]=A.mat[0][1]=A.mat[1][0]=1;
        A.mat[1][1]=0;
        Mat A_=Pow(A,x-1);
        return A_.mat[0][0];
    }
    LL polya(LL n)
    {
        if(n==1) return 2;
        LL ans=0,i;
        for(i=1;i*i<n;i++)
        if(n%i==0)
        {
            ans=(ans+Eular(i)*(fib(n/i-1)+fib(n/i+1)))%mod;
            ans=(ans+Eular(n/i)*(fib(i-1)+fib(i+1)))%mod;
        }
        if(i*i==n) ans+=Eular(i)*(fib(i-1)+fib(i+1))%mod;
        return ans*inv(n)%mod;
    }
    int main()
    {
        LL n;
        while(cin>>n)
            cout<<polya(n)<<'
    ';
    }
  • 相关阅读:
    [.Net 5.0] 笔记
    java计算两个字符串日期的相差天数
    记一个使用fyne-cross编译的坑
    windows gcc 遇到的问题解决
    异步处理在支付环节的应用
    怎么修复 "replaceAll is not a function" JavaScript Error?
    Js生成随机数 生成随机字符串的5种方法
    json-bigint的介绍和使用-解决Javascript的有关大整数问题
    国产操作系统——银河麒麟V10 SP1使用小结
    【转载】 银河麒麟V10系统安装U盘制作
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/6119497.html
Copyright © 2020-2023  润新知