zoukankan      html  css  js  c++  java
  • [poj2154]color

    题面:

    Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of the necklace can be produced. You should know that the necklace might not use up all the N colors, and the repetitions that are produced by rotation around the center of the circular necklace are all neglected.
    You only need to output the answer module a given number P.

    INPUT:

    The first line of the input is an integer X (X <= 3500) representing the number of test cases. The following X lines each contains two numbers N and P (1 <= N <= 1000000000, 1 <= P <= 30000), representing a test case.

    大意:给你X个项链,每个项链有n个珠子,用n种颜色染(颜色可以不全用),求本质不同的项链方案,当且仅当一个项链任意旋转(只有旋转没有翻转)都与其他项链不同是

    一开始没有仔细看题面,原来没有翻转,只有旋转

    SOLUTION:如果没有(N<=10^9),这道题就是一道裸题,直接根据polya定理计算即可,但是这道题N很大,不能直接计算,我们需要优化:

    (ans=sumlimits_{i=0}^{n-1}n^{gcd(i,n)})

    (d=gcd(i,n)),(d)一定是(n)的约数,我们可以先O((sqrt{n}))处理出(n)的约数,计算每个d贡献多少次,也就是有多少个i,(gcd(i,n)=d ext{转化为}gcd(frac{i}{d},frac{n}{d})=1),即(varphi(frac{n}{d})个),我们可以用欧拉函数
    注意我们在用polya/burnside定理时最后要除以置换集的大小,以为没有翻转,我们只用除以n(不用2n),但是是在(%p)意义下,p不一定是质数所以可能没有逆元,我们直接将公式改成(varphi(n/d) imes n^{d-1})

    code:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int t,n,p,tot,cnt;
    int prime[1000000],v[1000000];
    inline void pre(){
     for(int i=2;i<=100000;++i){
      if(!v[i]){
       prime[++tot]=i;
       v[i]=i;
      }
      for(int j=1;j<=tot;++j){
       if(prime[j]*i>100000||prime[j]>v[i])break;
       v[i*prime[j]]=prime[j];
      }
     }
    }
    inline int poww(int a,int b){
         int ans=1;
         while(b){
          if(b&1)ans=ans*a%p;
           a=a*a%p;
           b>>=1;
         }
         return ans%p;
    }
    inline int euler(int x){
     int ans=x;
     for(int i=1;i<=tot&&prime[i]*prime[i]<=x;++i){
      if(x%prime[i]==0){
                ans=ans/prime[i]*(prime[i]-1);
                while(x%prime[i]==0)x/=prime[i];
      }
     }
     if(x>1)ans=ans/x*(x-1);
     return ans;
    } 
    int main(){
     pre();
     cin>>t;
     for(int i=1;i<=t;++i){
           cin>>n>>p;
           int c=0;
           for(int j=1;j<=sqrt(n);++j){
             if(n%j==0){
              c=(c+euler(n/j)%p*poww(n%p,j-1)%p)%p;
              if(j*j!=n)c=(c+euler(j)%p*poww(n%p,n/j-1)%p)%p;
             }
           }
           cout<<c%p<<endl;
     }
     return 0;
    }
    
  • 相关阅读:
    kill process
    USB development guide
    MMC device
    memtester
    printf()格式化输出详解
    C语言动态内存分配
    归并排序C语言
    c 文件操作
    数据包分析
    C语言文件操作函数大全
  • 原文地址:https://www.cnblogs.com/ARTlover/p/9542161.html
Copyright © 2011-2022 走看看