poj 1286 Necklace of Beads

题目:http://poj.org/problem?id=1286

置换的第一题!

学习笔记:

置换
长为n的排列。其实是1~n到1~n的一个映射,值表示该位置对应之前的哪个位置。
置换的集合叫做置换群。
可用置换群来刻画题目中的(循环)同构。  //刻画的只是同构!所以并没有n!那么多个
(循环)不同构的方案数:每个置换下不动点个数的平均值
    不动点:在该数组上操作一次这个置换,等于没操作,这样的数组称为该置换下的不动点。
        (比如数组上每个位置的值都一样 之类的)
    一个置换的不动点个数:2^(该置换的环的个数)——环内的点要染成相同的颜色,不同的环之间不相互影响  //那个2因题而异
                    (因为环是转到的位置,为了不动,颜色要一样)
    一个长为n的环,每次顺时针转k步,这样的置换有多少个环?    //即环的旋转同构的个数
        k和n互质,则只有一个环。
            考虑角度:下一步的落脚点是p*k%n。p*k可以遍历%n剩余系。
        k和n不互质,可以遍历的是剩余系中gcd的倍数部分。所以为了遍历剩余系,需要gcd个环。
            证明:k和n互质,p在0~n-1范围内不能遍历%n剩余系的话:
                    p1*k=p2*k(mod n) -> (p1-p2)*k=0(mod n)
                因为k和n互质,所以k有逆元,可以同除k,得到p1-p2=0。
                  k和n不互质,令k0=k/gcd , n0=n/gcd,则p*k0可以遍历%n0的剩余系
                    乘上gcd后变成遍历n剩余系中gcd的倍数部分。

对于环有n(奇数)个点,共n条对称轴(每个点被踩一次),每个对称置换有(n-1)/2+1个环。(也就是(n+1)/2)

对于环有n(偶数)个点,共n条对称轴(踩在点上n/2个,踩在边上n/2个),踩在点上的有(n-2)/2+2个环(每个被踩的点自成一环),踩在边上的有n/2个环。

每个置换的不动点数是3^(环数)(因为能染三种颜色)。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll n,ans,cnt;
ll pw(ll x,int k)
{
    ll ret=1;while(k){if(k&1)ret*=x;x*=x;k>>=1;}return ret;
}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
    while(1)
    {
        scanf("%lld",&n);if(n==-1)return 0;
        if(!n){printf("0\n");continue;}
        ans=pw(3,n);cnt=2*n;
        for(int i=1;i<n;i++)ans+=pw(3,gcd(i,n));
        if(n&1)
            ans+=pw(3,((n-1)/2+1))*n;
        else
            ans+=pw(3,n/2)*n/2+pw(3,n/2+1)*n/2;
        printf("%lld\n",ans/cnt);
    }
}

 

posted on 2018-07-01 20:39  Narh  阅读(89)  评论(0编辑  收藏  举报

导航