• poj 2154:Color【polya计数,Euler函数】



    http://poj.org/problem?id=2154

    poj 2154:Color
    http://blog.sina.com.cn/s/blog_6f71bea30100opru.html

    大意:n种颜色的珠子可组成多少种长度为n的项链?
    这题和2409 类似,不同之处在于,只考虑旋转,不考虑翻转;
    因此相对前面两个题目应该说是更简单,但一看数据范围,
    就不是这么回事了,2409完全可以直接循环处理,
    但这题目n最大达100000000,显然会TLE,故需寻求更佳的解决方案。
    用欧拉函数进行优化:

    旋转:顺时针旋转i格的置换中,循环的个数为gcd(i,n),每个循环的长度L为n/gcd(i,n)。
    如果枚举旋转的格数i,复杂度显然较高。有没有好方法呢?可以不枚举i,反过来枚举L。
    由于L|N,枚举了L,再计算有多少个i使得0<=i<=n-1并且gcd(i,n)=n/L。
    不妨设a=n/L=gcd(i, n),
    不妨设i=a*t则当且仅当gcd(L,t)=1时
    Gcd(i,n)=gcd(a*L,a*t)=a。
    因为0<=i<n,所以0<=t<n/a=L.
    所以满足这个条件的t的个数为Euler(L).

    #include<stdio.h>
    #include<string.h>
    
    const int N = 36000;
    int prime[N];
    int pnum;
    bool isp[N];
    int  mod;
    void getPrim()
    {
     int i,j;
     pnum = 0;
     memset(isp,true,sizeof(isp));
     for(i=2;i<N;i++)
      if(isp[i])
      {
       prime[pnum++]=i;
       for(j=i+i;j<N;j+=i)
        isp[j]=false;
      }
    
     // for(i=0;i<10;i++)
      // printf("%d ",prime[i]);
    }
    
    int  Eular(int  n)
    {
       int  i;
       int  ret = n;
       if(n==1)return 1;
       for(i=0;prime[i]*prime[i]<=n;i++)
       {
        if(n%prime[i]==0)
        {
         ret-=ret/prime[i];
         while(n%prime[i]==0)n/=prime[i];
         if(n==1)break;
        }
       }
    
       if(n!=1)ret-=ret/n;
       return ret;
    }
    
     
    
    int  getPow(int  a,int  l,int  mod)
    {
     int  ans = 1;
     a=a%mod;
        while(l)
     {
      if(l&1)ans=(ans*a)%mod;
      l>>=1;
      a=(a*a)%mod;
     }
     return ans;
    }
    int main()
    {
     getPrim();
     int T;
     scanf("%d",&T);
     {
           while(T--)
        {
         int  a,l;
         int  ans = 0;
         scanf("%d%d",&a,&mod);
         for(l=1;l*l<a;l++)
         {
          if(a%l==0)
          {
                     int  x = Eular(l)%mod;
         int  c = getPow(a,a/l-1,mod);
         ans=(ans+c*x%mod)%mod;
          x = Eular(a/l)%mod;
          c = getPow(a,l-1,mod);
          ans=(ans+c*x%mod)%mod;
          }
         }
         if(l*l==a)
         {
                  int  x = Eular(l)%mod;
         int  c = getPow(a,a/l-1,mod);
         ans=(ans+c*x%mod)%mod;
         }
    
         printf("%d\n",ans);
        }
    
    
     }
     return 0;
    }
    
  • 相关阅读:
    windows C++ 网络编程
    typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针
    获取屏幕分辨率(C/C++)
    随手记
    【SQLite】可视化工具SQLite studio
    C++宽窄字符串转换
    并发编程1——一个简单的多线程程序
    css中:after和:before的作用及使用方法
    uniapp—App—自定义导航栏
    vue—封装无数据时默认展示组件
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1956201.html
Copyright © 2020-2023  润新知