zoukankan      html  css  js  c++  java
  • POJ 2154 【POLYA】【欧拉】

    前记:

    TM终于决定以后干啥了。这几天睡的有点多。困饿交加之间喝了好多水。可能是灌脑了。

    切记两件事:

    1.安心当单身狗

    2.顺心码代码

    题意:

    给你N种颜色的珠子,串一串长度问N的项链,要求旋转之后重合的算是同一种项链。问一共有多少中可能。结果模p。

    1 <= N <= 1000000000, 1 <= P <= 30000

    思路:

    首先是我们的POLYA定理,给定的公式是这样的sigma(N^gcd(N,i))/N   i从0到N-1.

    然后是优化的问题。因为如果我们枚举i累加一定会超时。

    这道题考虑的是gcd(N,i)的种类是有限的。我们只要求出每种gcd有多少个就可以了。

    考虑N=X*GCD I=Y*GCD

    由此我们知道gcd(x,y)一定是1.

    所以考虑枚举x,GCD的个数应该是x的欧拉。

    坑点:

    春困。TM变量总是写错。这道题的减一来源于提前把N给除掉了【这个N经常容易被人忽略】

    #include<iostream>
    #include<math.h>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    int prime[100000];//0代表是素数
    int tmp[100000];//素数的序列
    int part[100000];//将t分解
    int num[100000];//每个质因数的分解数量
    int jilu[100000];//dfs记录某个质因数用了几个
    long long ans,t,p;//t是N,p是p
    int partn;//记录一共分解成了几种素数
    void fprime()//筛法打表
    {
        int atmp=0,j;
        for(int i=2;i<100000;i++)
        {
            if(!prime[i])
            {
                tmp[atmp++]=i;
            }
            for(j=0;j<atmp;j++)
            {
                if(i*tmp[j]>=100000)
                    break;
                prime[i*tmp[j]]=1;
                if(i%tmp[j]==0)
                    break;
            }
        }
    }
    void depart(int t){
        int sq=sqrt(t)+1;
        for(int i=0;tmp[i]<=sq;i++){
                if(t%tmp[i]==0){
                    part[partn]=tmp[i];
                    while(t%tmp[i]==0){
                        num[partn]++;
                        t/=tmp[i];
                    }
                    partn++;
                }
        }
        if(t>1){
            part[partn]=t;
            num[partn]=1;
            partn++;
        }
    }
    void init(){
        memset(num,0,sizeof(num));
        partn=0;
        ans=0;
    }
    long long quick_pow(long long a,long long b){
        long long rel=1;
        while(b){
            if(b&1){
                rel*=a;
                rel%=p;
            }
            a*=a;
            a%=p;
            b>>=1;
        }
        return rel;
    }
    long long oula(){
        long long rel=1;
        for(int i=0;i<=partn;i++){
            if(jilu[i]){
                rel*=(part[i]-1)*quick_pow(part[i],jilu[i]-1);
                rel%=p;
            }
        }
        return rel;
    }
    void dfs(int pos,long long nnum){
        if(pos>partn){
            long long a=oula();
            long long b=quick_pow(t,t/nnum-1);
            ans+=(a%p)*(b%p)%p;
            ans%=p;
            return;
        }
        long long ttt=1;
        for(int i=0;i<=num[pos];i++){
            jilu[pos]=i;
            dfs(pos+1,nnum*ttt);
            ttt*=part[pos];
        }
    }
    int main()
    {
        fprime();
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%I64d%I64d",&t,&p);
            init();
            depart(t);
            partn--;
            dfs(0,1);
            printf("%I64d
    ",ans);
        }
    }
  • 相关阅读:
    HDU 4389 数位dp
    Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)A B C 水 并查集 思路
    Codeforces Round #385 (Div. 2)A B C 模拟 水 并查集
    Codeforces Round #404 (Div. 2)A B C二分
    HDU 2586 倍增法求lca
    Codeforces Round #209 (Div. 2)A贪心 B思路 C思路+快速幂
    Codeforces Round #384 (Div. 2) A B C D dfs序+求两个不相交区间 最大权值和
    vim出现“E212: Can't open file for writing”的处理办法
    centos7 开机/etc/rc.local 不执行的问题
    CentOS 系统状况查看
  • 原文地址:https://www.cnblogs.com/tun117/p/5295763.html
Copyright © 2011-2022 走看看