zoukankan      html  css  js  c++  java
  • HDU3430 (置换群循环节+中国剩余定理)

    题意:给出n张牌,标号为1-n,然后给出两个序列,序列1表示序列1,2,3,4……,n洗一次牌后到达的,序列2表示目标序列,问初始序列按序列1的洗牌方式洗几次能到达序列2的情况,如果不能到达输出-1。

    题解:在初始序列和序列1的变换中找出1能变到那些牌,这些牌构成一个集合,这些集合中的牌必然是能够相互到达的,然后在序列2中也找出这样一个集合,集合中这些元素的相互顺序是要一样的,这就是判断能否达到,然后这样可以列出几个线性同余方程组,用中国剩余定理求解即可(顺便献上中国剩余定理模板)。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    using namespace std;
    int n,a[1001],b[1001],vis[1001],c[1001],x[1001],y[1001];
    long long exgcd(long long a,long long b,long long &x,long long &y)
    {
        if (b==0)
        {
            x=1;
            y=0;
            return a;
        }
        long long gcd=exgcd(b,a%b,x,y);
        long long t=x;
        x=y;
        y=t-a/b*x;
        return gcd;
    }
    long long china_remain(long long m,int a[],int b[])
    {
        //for (int i=1;i<=m;i++)
        //    cout<<a[i]<<" "<<b[i]<<endl;
        long long a1,a2,b1,b2,x,y,flag=0;
        a1=a[0];
        b1=b[0];
        int i;
        for (i=1;i<m;i++)
        {
            a2=a[i];
            b2=b[i];
            long long gcd=exgcd(a1,a2,x,y);
            if ((b2-b1)%gcd)
            {
                flag=1;
                break;
            }
            long long t=a2/gcd;
            x=(x*(b2-b1))/gcd;
            x=(x%t+t)%t;
            b1=a1*x+b1;
            a1=(a1*a2)/gcd;
            b1=(b1%a1+a1)%a1;
        }
        if (flag) return -1;
        return b1;
    }
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) break;
            int i;
            for (i=1;i<=n;i++) scanf("%d",&a[i]);
            for (i=1;i<=n;i++) scanf("%d",&b[i]);
            memset(vis,0,sizeof(vis));
            int cnt=0;
            bool can=true;
            for (i=1;i<=n;i++) if (!vis[i])
            {
                int flag=i;
                int count=0;
                while (!vis[flag])
                {
                    vis[flag]=1;
                    c[count++]=flag;
                    flag=a[flag];
                }
                int pos=0;
                while (pos<count&&b[i]!=c[pos]) pos++;
                if (pos==count)
                {
                    can=false;
                    break;
                }
                x[cnt]=count;
                y[cnt++]=pos;
                //cout<<count<<" "<<pos<<endl;
                flag=a[i];
                while (flag!=i)
                {
                    if (b[flag]!=c[(++pos)%count])
                    {
                        can=false;
                        break;
                    }
                    flag=a[flag];
                }
                if (!can) break;
            }
            if (!can) puts("-1");
            else printf("%lld
    ",china_remain(cnt,x,y));
        }
    }
  • 相关阅读:
    Ubuntu12.04 亮度调节和保存
    算法
    Python一些常见问题的解决方法
    数据结构
    C# 运行时编译代码并执行 【转】
    C# 动态添加属性 非原创 有修改
    30天学通Visual C++项目案例开发 下載
    .NET常用Request获取信息
    获取一个目录下所有的文件,包括子目录的
    C++入门到精通_全集下载
  • 原文地址:https://www.cnblogs.com/hnqw1214/p/6602341.html
Copyright © 2011-2022 走看看