zoukankan      html  css  js  c++  java
  • poj 1286 Necklace of Beads (polya(旋转+翻转)+模板)

     

    Description

    Beads of red, blue or green colors are connected together into a circular necklace of n beads ( n < 24 ). If the repetitions that are produced by rotation around the center of the circular necklace or reflection to the axis of symmetry are all neglected, how many different forms of the necklace are there? 

    Input

    The input has several lines, and each line contains the input data n. 
    -1 denotes the end of the input file. 

    Output

    The output should contain the output data: Number of different forms, in each line correspondent to the input data.

    Sample Input

    4
    5
    -1

    Sample Output

    21
    39

    Source

     

    1、题目类型:Polya定理、组合数学、置换群。

    2、解题思路:Polya定理:(1)设G是p个对象的一个置换群,用k种颜色突然这p个对象,若一种染色方案在群G的作用下变为另一种方案,则这两个方案当作是同一种方案,这样的不同染色方案数为:

    (2)置换及循环节数的计算方法:对于有n个位置的手镯,有n种旋转置换和n种翻转置换.
                                              对于旋转置换: c(fi) = gcd(n,i)  i为一次转过i颗宝石( i = 0 时 c=n;);
                                              对于翻转置换:如果n为偶数:c(f) = n/2 的置换有n/2个; 
                                                                                c(f) = n/2+1 的置换有n/2个;
                                                               如果n为奇数:c(f) = n/2+1.

    3、注意事项:注意对于翻转置换过程中对于奇偶数情况的区分处理。

    相同的gcd合并在一起计算:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<map>
     5 #include<set>
     6 #include<vector>
     7 using namespace std;
     8 #define ll long long
     9 ll pow_mod(ll a,ll i){
    10     if(i==0)
    11         return 1;
    12     ll t=pow_mod(a,i/2);
    13     ll ans=t*t;
    14     if(i&1)
    15         ans=ans*a;
    16     return ans;
    17 }
    18 
    19 
    20 
    21 vector<ll> divisor(ll n){
    22     vector<ll> res;
    23     for(ll i=1;i*i<=n;i++){
    24         if(n%i==0){
    25             res.push_back(i);
    26             if(i*i!=n){
    27                 res.push_back(n/i);
    28             }
    29         }
    30     }
    31     return res;
    32 }
    33 ll eular(ll n){
    34     ll res=1;
    35     for(ll i=2;i*i<=n;i++){
    36         if(n%i==0){
    37             n/=i,res*=i-1;
    38             while(n%i==0){
    39                 n/=i;
    40                 res*=i;
    41             }
    42         }
    43     }
    44     if(n>1) res*=n-1;
    45     return res;
    46 }
    47 ll polya(ll m,ll n){
    48     //map<ll,ll> primes = prime_factor(n);
    49     vector<ll> divs = divisor(n);
    50     ll res=0;
    51     for(ll i=0;i<divs.size();i++){
    52         ll euler=eular(divs[i]);
    53         res+=euler*pow_mod(m,n/divs[i]);
    54     }
    55     res/=n;
    56     return res;
    57 }
    58 int main()
    59 {
    60     ll n,m=3;
    61     while(~scanf("%I64d",&n) && n!=-1){
    62         if(n==0){
    63             puts("0");
    64             continue;
    65         }
    66         ll count=polya(m,n)*n;//旋转情况 
    67         if(n&1){//奇数 
    68             count+=n*pow_mod(m,n/2+1);//翻转情况 
    69         }
    70         else{//偶数 
    71             count += (pow_mod(m, n / 2 + 1) + pow_mod(m, n / 2)) * (n / 2);//翻转情况 
    72         }
    73         count/=2*n;
    74         printf("%I64d
    ",count);
    75     }
    76     return 0;
    77 }
    View Code

    附上大神代码:

    相同的gcd合并在一起计算:

      1 #include <iostream>
      2 #include <map>
      3 #include <vector>
      4 using namespace std;
      5  
      6 #define LL long long
      7  
      8 inline LL power(LL p, LL n)
      9 {
     10     LL sum = 1;
     11     while (n)
     12     {
     13         if (n & 1)
     14             sum *= p;
     15         p *= p;
     16         n /= 2;
     17     }
     18     return sum;
     19 }
     20  
     21 //************************************
     22 // Method:    divisor
     23 // FullName:  divisor
     24 // Access:    public 
     25 // Returns:   vector<int> 约数
     26 // Qualifier: 约数枚举
     27 // Parameter: const int & n 目标数n
     28 //************************************
     29 vector<int> divisor(const int& n)
     30 {
     31     vector<int> res;
     32     for (int i = 1; i * i <= n; ++i)
     33     {
     34         if (n % i == 0)
     35         {
     36             res.push_back(i);
     37             if (i != n / i)
     38             {
     39                 res.push_back(n / i);
     40             }
     41         }
     42     }
     43  
     44     return res;
     45 }
     46  
     47 //************************************
     48 // Method:    prime_factor
     49 // FullName:  prime_factor
     50 // Access:    public 
     51 // Returns:   map<int, int>
     52 // Qualifier: 整数分解
     53 // Parameter: int n
     54 //************************************
     55 map<int, int> prime_factor(int n)
     56 {
     57     map<int, int> res;
     58     for (int i = 2; i * i <= n; ++i)
     59     {
     60         while (n % i == 0)
     61         {
     62             ++res[i];
     63             n /= i;
     64         }
     65     }
     66     if (n != 1)
     67     {
     68         res[n] = 1;
     69     }
     70     return res;
     71 }
     72  
     73 LL polya(const int& m, const int& n)
     74 {
     75     map<int, int> primes = prime_factor(n);
     76     vector<int> divs = divisor(n);
     77     LL res = 0;
     78     for (int i = 0; i < divs.size(); ++i)
     79     {
     80         // 求divs[i]的欧拉函数值
     81         LL euler = divs[i];
     82         for (map<int, int>::iterator it = primes.begin(); it != primes.end(); ++it)
     83         {
     84             int p = it->first;
     85             if (divs[i] % p == 0) euler = euler / p * (p - 1);
     86         }
     87  
     88         res += euler * power(m, n / divs[i]);
     89     }
     90  
     91     // 最后除以n
     92     res /= n;
     93     return res;
     94 }
     95  
     96 ///////////////////////////SubMain//////////////////////////////////
     97 int main(int argc, char *argv[])
     98 {
     99 #ifndef ONLINE_JUDGE
    100     freopen("in.txt", "r", stdin);
    101     freopen("out.txt", "w", stdout);
    102 #endif
    103     int n; const LL m = 3;
    104     while (~scanf("%d", &n) && n != -1)
    105     {
    106         if (n == 0)
    107         {
    108             puts("0");
    109             continue;
    110         }
    111  
    112         LL count = polya(m, n) * n;
    113         if (n & 1)
    114             count += n * power(m, n / 2 + 1);
    115         else
    116             count += (power(m, n / 2 + 1) + power(m, n / 2)) * (n / 2);
    117         count /= 2 * n;
    118         printf("%lld
    ", count);
    119     }
    120 #ifndef ONLINE_JUDGE
    121     fclose(stdin);
    122     fclose(stdout);
    123     system("out.txt");
    124 #endif
    125     return 0;
    126 }
    View Code

    还有一种暴力求法:

     1 #include <iostream>
     2 using namespace std;
     3  
     4 #define LL long long
     5  
     6 int gcd(int a, int b)
     7 {
     8     return b == 0 ? a : gcd(b, a % b);
     9 }
    10  
    11 LL power(LL p, LL n)
    12 {
    13     LL sum = 1;
    14     while (n)
    15     {
    16         if (n & 1)
    17             sum *= p;
    18         p *= p;
    19         n /= 2;
    20  
    21     }
    22     return sum;
    23 }
    24  
    25 ///////////////////////////SubMain//////////////////////////////////
    26 int main(int argc, char *argv[])
    27 {
    28 #ifndef ONLINE_JUDGE
    29     freopen("in.txt", "r", stdin);
    30     freopen("out.txt", "w", stdout);
    31 #endif
    32     int n; const LL m = 3;
    33     while (~scanf("%d", &n) && n != -1)
    34     {
    35         if (n == 0)
    36         {
    37             puts("0");
    38             continue;
    39         }
    40         LL count = 0;
    41         for (int i = 1; i <= n; ++i)
    42             count += power(m, gcd(i, n));
    43         if (n & 1)
    44             count += n * power(m, n / 2 + 1);
    45         else
    46             count += n / 2 * (power(m, n / 2 + 1) + power(m, n / 2));
    47         count /= n * 2;
    48         printf("%lld
    ", count);
    49     }
    50 #ifndef ONLINE_JUDGE
    51     fclose(stdin);
    52     fclose(stdout);
    53     system("out.txt");
    54 #endif
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    Java多线程 编写三各类Ticket、SaleWindow、TicketSaleCenter分别代表票信息、售票窗口、售票中心。 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
    java中异常处理机制 throw抛出自定义业务逻辑异常 throws继续抛出 catch捕获后会自动继续抛向调用方法
    Map集合应用 取出一个字符串中字母出现的次数。如:字符串:"abcdekka27qoq" ,输出格式为:a(2)b(1)k(2)...
    Java中List集合排序的方法 比较器的使用 根据学生对象数学 语文 英语成绩总和进行sort排序
    美国银行
    Time Difference
    马来西亚与新加坡两国的标准时间为UTC+8
    java主要城市时区对照表
    韩国时区 KST
    AIX 系统
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4776566.html
Copyright © 2011-2022 走看看