POJ置换群入门[3/3]

POJ 3270 Cow Sorting

题意:

一个序列变为升序,操作为交换两个元素,代价为两元素之和,求最小代价

题解:

看了黑书...

首先循环因子分解

一个循环完成的最小代价要么是循环中最小元素依次与其他交换,要么引入全局最小值来交换

$sum+min(mn*(len-2),mn+Min*(len+1))$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e4+5,M=1e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
int n,a[N],c[M],Min=M,m;
int f[N],ans;
bool vis[N];
int main(){
    //freopen("in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),c[a[i]]++,Min=min(Min,a[i]),m=max(m,a[i]);
    for(int i=1;i<=m;i++) c[i]+=c[i-1];
    for(int i=1;i<=n;i++) f[i]=c[a[i]];
    for(int i=1;i<=n;i++) if(!vis[i]){
        vis[i]=1;
        int u=f[i],sum=a[i],mn=a[i],len=1;
        while(u!=i) vis[u]=1,sum+=a[u],mn=min(mn,a[u]),len++,u=f[u];
        ans+=sum+min(mn*(len-2),mn+Min*(len+1));
    }
    printf("%d",ans);
}
View Code

 

POJ2369 Permutations

题意:

求一个置换的几次幂得到自身

题解:

每个循环长度的最小公倍数

注意是几次幂不是转换了几次!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e3+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
int n,a[N],ans=1;
inline int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
inline int lcm(int a,int b){return a/gcd(a,b)*b;}
bool vis[N];
int main(){
    //freopen("in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++) if(!vis[i]){
        vis[i]=1;
        int u=a[i],len=1;
        while(u!=i) vis[i]=1,len++,u=a[u];
        ans=lcm(ans,len);
    }
    printf("%d",ans);
}
View Code

 

POJ1721CARDS

题意:

交换规则为$i \rightarrow a[a[i]]$,进行了$s$次,给出最后的排列求一开始

题解:

一直尝试构造置换的逆一直失败,也许是因为每次合成的置换都不同吧

网上的做法是暴力找整个置换的循环然后把剩下的操作补出来...感觉会被卡...

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1005;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
int n,s,a[N],t[N],b[N];
int main(){
    freopen("in","r",stdin);
    n=read();s=read();
    for(int i=1;i<=n;i++) b[i]=a[i]=read();
    int cnt=0;
    while(true){
        int flag=1;
        cnt++;
        for(int i=1;i<=n;i++) t[i]=a[a[i]];
        for(int i=1;i<=n;i++){
            a[i]=t[i];
            if(a[i]!=b[i]) flag=0;
        }
        if(flag) break;
    }
    cnt=cnt-s%cnt;
    while(cnt--){
        for(int i=1;i<=n;i++) t[i]=a[a[i]];
        for(int i=1;i<=n;i++) a[i]=t[i];
    }
    for(int i=1;i<=n;i++) printf("%d\n",a[i]);
}
View Code

 

posted @ 2017-02-28 10:15  Candy?  阅读(422)  评论(0编辑  收藏  举报