zoukankan      html  css  js  c++  java
  • 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 ightarrow 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
    ",a[i]);
    }
    View Code
  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/candy99/p/6477599.html
Copyright © 2011-2022 走看看