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); }
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); }
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]); }
Copyright:http://www.cnblogs.com/candy99/