置换群快速幂 学习小结 #by nobody

来源:互联网 发布:创博网络 编辑:程序博客网 时间:2024/06/04 23:26

本小结会不断更新,转载注明出处:http://blog.csdn.net/xdu_truth/article/details/8040080


上个月在hdu热身赛中遇到一个数学题(hdu 4259),本来以为是个找规律的题,想了一下午没想出来。

后来看了解答,觉得好神奇的样子。这几天自学了一下置换群才恍然大悟那题是个很基础的置换群的题。
数学真是博大精深啊。。


结论一:一个长度为l的循环T,l是k的倍数,则T是k个循环的乘积,每个循环分别是循环T中下标i mod k=0,1,2…的元素按顺序的连接。
结论二:一个长度为l的循环T,gcd(l,k)=1,则T是一个循环,与循环T不一定相同。
结论三:一个长度为l的循环T,T是gcd(l,k)个循环的乘积,每个循环分别是循环T中下标i mod gcd(l,k)=0,1,2…的元素的连接。
参见论文《置换群快速幂运算+研究与探讨》和《组合数学》最后一章


下面是一些刷题小结,我会不断更新

----------------------------------------------------------纯洁的分割线----------------------------------------------------------------------

poj 3270
一个关于排序的经典应用,题目和解析可以参见黑书P247例题。
附代码:


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct circle{    int t,k,sum;    circle(){sum = 0;k = 0;t = 1<<30;}};int a[10100],b[10100];int flag[10100];int n;int main(){    //freopen("input.txt","r",stdin);    while(~scanf("%d",&n))    {        int m = 1<<30;        for(int i=0;i<n;i++)        {            scanf("%d",&a[i]);            b[i] = a[i];            m = min(m,a[i]);        }        sort(b,b+n);        circle c[10100];        int tot = 0;        memset(flag,false,sizeof(flag));        for(int i=0;i<n;i++)        {            if(flag[i])continue;            flag[i] = true;            if(a[i] == b[i])continue;            c[tot].sum += a[i];            c[tot].t = a[i];            c[tot].k++;            int temp = b[i];            while(temp != a[i])            {                c[tot].k++;                c[tot].sum += temp;                c[tot].t = min(c[tot].t,temp);                for(int j=0;j<n;j++)                {                    if(a[j]!= temp || flag[j])continue;                    flag[j] = true;                    if(a[j]==b[j])continue;                    temp = b[j];                    break;                }            }            tot++;        }        int cost = 0;        for(int i=0;i<tot;i++)        {            cost += c[i].sum+min((c[i].k - 2)*c[i].t,c[i].t + (c[i].k+1)*m);   //黑书上最后的那个公式,注意它的推导。        }        printf("%d\n",cost);    }    return 0;}
---------------------------------------------------------------华丽的分割线---------------------------------------------------------------------------------------

poj1026

问题描述:给一个置换群, 然后 给出一个字符串 需要让你帮他加密M次
其中原串不足的地方用‘ ’补足
解析:最简单的置换群,找周期就行了。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int a[210],b[210],len[210];char str[210];int n,k;int main(){    freopen("input.txt","r",stdin);    while(scanf("%d",&n),n)    {            for(int i=0;i<n;i++)            {                int t;                scanf("%d",&t);                t--;                a[t] = i;            }            memset(len,0,sizeof(len));            for(int i=0;i<n;i++)            {                int t = a[i];                len[i]++;                while(a[i]!=a[t])                {                    len[i]++;                    t = a[t];                }            }            while(scanf("%d",&k),k)            {                char ch;                scanf("%c",&ch);//                int cnt = 0;                while(1)                {                    scanf("%c",&str[cnt]);                    if(str[cnt]=='\n')break;                    cnt++;                }                if(cnt < n)                {                    for(int i=cnt;i<n;i++)                        str[i] = ' ';                }                for(int i=0;i<n;i++)                    b[i] = i;                for(int i=0;i<n;i++)                    for(int j=0;j<k%len[i];j++)                        b[i] = a[b[i]];                for(int i=0;i<n;i++)                    printf("%c",str[b[i]]);                printf("\n");            }            printf("\n");    }    return 0;}


原创粉丝点击