zoukankan      html  css  js  c++  java
  • POJ 2154 Color (Polya计数)

      题意:给你N种颜色的珠子,个数不限,串成一个长度为N的项链,经过旋转以后,问能形成多少等价类

      分析:套用Polya定理的计数公式即可,题目中的旋转操作可以形成N个置换,假设旋转了i个珠子,那么这个置换的置换环个数为gcd(i,N),但是这里N比较大,需要枚举N的所有因子然后欧拉函数优化。这个题当时我还在想模的数不是质数,逆元怎么办,然后才发现置换群的大小是N,颜色的个数也是N,不需要逆元(笑哭),还有就是这题数据挺强的,时间上尽量多优化一些。

      代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define LL long long
    const int N = 1e6+6;
    bool isp[N];
    int cnt,P[78598];
    LL ol[N];
    void init(){
        cnt=0; int up = 1000000;
        for(int i=2;i<=up;i++){
            if(!isp[i]){
                P[cnt++]=i;
                ol[i] = i-1;
            }
            for(int j=0;j<cnt;j++){
                LL tmp = P[j]*i;
                if(tmp > up) break;
                isp[tmp] = 1;
                if(i%P[j] == 0){
                    ol[tmp] = ol[i]*P[j];
                    break;
                }else {
                    ol[tmp] = ol[i]*(P[j]-1);
                }
            }
        }
        ol[1] = 1;
    //    cout<<cnt<<endl;
    }
    int p;
    LL Euler(LL n){
        if(n <= 1000000) return ol[n];
        LL res = n;
        for(int i=0;i<cnt;i++){
            LL tmp = 1LL*P[i]*P[i];
            if(tmp > n) break;
            if(n%P[i] == 0){
                res = res/P[i]*(P[i]-1);
            }
            while(n%P[i] == 0) n/=P[i];
        }
        if(n!=1) res = res/n*(n-1);
        return res%p;
    }
    LL Pow(LL x,int y){
        LL res = 1;
        while(y){
            if(y&1){
                res=(res*x)%p;
            }
            x=(x*x)%p;
            y>>=1;
        }
        return res;
    }
    int read(){
        int res=0; char ch;
        while((ch=getchar())){
            if(ch>='0'&&ch<='9'){
                res = ch-'0';
                break;
            }
        }
        while((ch=getchar())){
            if(ch<'0'||ch>'9') break;
            res *= 10;
            res += ch-'0';
        }
        return res;
    }
    int main(){
        init();
        int T,n;
        T = read();
        while(T--){
            n = read(); p = read();
            LL ans = 0;
            for(int i=1;i*i<=n;i++){
                if(n%i == 0){
                    ans=(ans+(Euler(n/i)*Pow(n,i-1))%p)%p;
                    int p2 = n/i;
                    if(p2!=i) {
                        ans=(ans+(Euler(n/p2)*Pow(n,p2-1))%p)%p;
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    linux下将可执行程序进行打包
    多节点OpenMPI集群的搭建和使用
    快排
    git 出现:warning: LF will be replaced by CRLF in
    String 根据 第一个逗号去掉逗好后面的内容
    SpringBoot项目中想去掉数据库查询到的数组双括号
    mybatis-plus多条件 or 的使用
    从linux上的docker持久化mysql数据恢复到本地mysql数据库
    @Repository和@Mapper
    JavaScript动画实例:爆裂的粒子
  • 原文地址:https://www.cnblogs.com/jifahu/p/7860391.html
Copyright © 2011-2022 走看看