zoukankan      html  css  js  c++  java
  • polya置换

    UVA10294

    POLYA定理的基本应用

    题意:
    有n个珠子围成的环,有t种颜色可以染这些珠子;
    如果这个环可以旋转有几种办法;
    如果这个环可以旋转,且可以翻转,有几种办法;

    参考博客

    刘汝佳的分析:

           等价类计数问题。一共有两种置换,选择以及翻转。项链只有第一种置换,手镯则有两种置换。设所有珠子按逆时针编号0~n-1。

           旋转置换:如果逆时针旋转i颗珠子的间距,则珠子0、i、2i、…构成一个循环。这个循环有n/gcd(i,n)个元素。根据对称性,所有循环的长度相同,因此一共有n/(n/gcd(i,n)) = gcd(i,n)个循环。该置换的不动点数为t^(gcd(i,n))。所有置换的不动点总数为a = sum{t^gcd(i,n) | i = 0,1,…,n - 1}。

           翻转置换:分情况讨论。当n是奇数时,对称轴有n条,每条对称轴形成(n-1)/2个长为2的循环以及1个长为1的循环,即(n+1)/2个循环。这些置换的不动点总数是b=nt^((n+1)/2)。

    当n是偶数时,有两种对称轴。穿过珠子的对称轴有n/2条,各形成n/2-1个长为2的循环,还形成两个长为1的循环;不穿过珠子的对称轴有n/2条,各形成n/2个长为2的循环。这些置换的不动点总数是b = n / 2 * (t ^ (n / 2 + 1) + t ^ (n / 2))。

           根据Polya定理,项链总数为a/n,手镯总数是(a + b) / (2n)。

     1 #include<bits/stdc++.h>
     2 #define mp make_pair
     3 #define pb push_back
     4 #define first fi
     5 #define second se
     6 #define pw(x) (1ll << (x))
     7 #define sz(x) ((int)(x).size())
     8 #define all(x) (x).begin(),(x).end()
     9 #define rep(i,l,r) for(int i=(l);i<(r);i++)
    10 #define per(i,r,l) for(int i=(r);i>=(l);i--)
    11 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
    12 #define eps 1e-9
    13 #define PIE acos(-1)
    14 #define cl(a,b) memset(a,b,sizeof(a))
    15 #define fastio ios::sync_with_stdio(false);cin.tie(0);
    16 #define lson l , mid , ls
    17 #define rson mid + 1 , r , rs
    18 #define ls (rt<<1)
    19 #define rs (ls|1)
    20 #define INF 0x3f3f3f3f
    21 #define LINF 0x3f3f3f3f3f3f3f3f
    22 #define freopen freopen("in.txt","r",stdin);
    23 #define cfin ifstream cin("in.txt");
    24 #define lowbit(x) (x&(-x))
    25 #define sqr(a) a*a
    26 #define ll long long
    27 #define ull unsigned long long
    28 #define vi vector<int>
    29 #define pii pair<int, int>
    30 #define dd(x) cout << #x << " = " << (x) << ", "
    31 #define de(x) cout << #x << " = " << (x) << "
    "
    32 #define endl "
    "
    33 using namespace std;
    34 //**********************************
    35 int n,t;
    36 ll f[17];
    37 //**********************************
    38 void get(int n)
    39 {
    40     f[0]=1;
    41     FOR(i,1,n)f[i]=f[i-1]*t;
    42 }
    43 inline int gcd(int a,int b)
    44 {
    45     return b==0?a:gcd(b,a%b);
    46 }
    47 //**********************************
    48 int main()
    49 {
    50     while(~scanf("%d%d",&n,&t)){
    51         get(n);
    52         ll a=0,b=0;
    53         rep(i,0,n)a+=f[gcd(i,n)];
    54         if(n%2==1)b=n*(f[(n+1)/2]);
    55         else b=n/2*(f[n/2+1]+f[n/2]);
    56         printf("%lld %lld
    ",a/n,(a+b)/2/n);
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    暴力程序之回文子串
    关于取消同步带来问题的样例
    JavaScript之Date
    JavaScript之array
    智破连环阵
    超长数字串
    无向图最短路径
    扫雷
    n!最末尾非0数
    计算程序运行时间
  • 原文地址:https://www.cnblogs.com/klaycf/p/9671243.html
Copyright © 2011-2022 走看看