hdu_3430 Shuffling

题目:

  A casino owns an expensive card shuffling machine which may shuffle up to 520 cards at a time (there are 52 cards in each deck). For convenience, we will simply label the cards 1, 2, 3, ..., N where N is the total number of cards, and copies of the same card (e.g. Ace of Spades) from different decks are considered different. Unfortunately, the card shuffling machine is defective, and it always shuffles the cards the same way. The company that produces these machines is out of business because of the economic downturn. There is no one who can fix the machine, and a new machine is too expensive.
  Being a brilliant employee of the casino, you realized that all is not lost. You can shuffle the cards differently simply by using the machine zero or more times. For example, suppose that the machine shuffles the cards 1, 2, 3, 4 into the order 2, 3, 4, 1. If you put the cards into the machine, take the shuffled cards out and insert them into the machine again (without changing the order), you will get the order 3, 4, 1, 2. That way, it is possible to shuffle the cards in many different ways even though it may take longer. But this is not a significant issue since decks do not have to be reshuffled often, and used decks can be shuffled while other decks are being used to avoid any waiting time.
  Unfortunately, not all shufflings can be produced in this way in general, and you wish to know if this procedure "stack the decks" in a favorable way for the casino or the player. As a first step, you wish to know which shufflings are possible to produce, and how many times you need to use the machine on the deck in order to produce the shuffling.

思路:

  求出每张牌要洗几次()才会循环,要洗几次()就能符合要求。
  那么就能列出方程组,中国剩余定理解方程即可。

代码:

#include <bits/stdc++.h>
#define ll long long
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
#define lcm(a,b) ((a)/gcd(a,b)*(b))
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
    if(!b){d=a;x=1;y=0;return;}
    exgcd(b,a%b,d,y,x);y-=a/b*x;
}
ll calc(ll a,ll b,ll c){
    ll x,y,d;
    exgcd(a,b,d,x,y);
    if(c%d)return -1;
    a/=d;b/=d;c/=d;
    return (x*c%b+b)%b;
}
struct CRT{
    ll A,M;
    CRT(){A=0;M=1;}
    bool insert(ll a,ll m){
        ll k=calc(M,m,a-A);
        if(!~k)return false;
        A+=M*k;
        M=lcm(M,m);
        return true;
    }
};
int to[525],ned[525],a[525],b[525];
bool vis[525];
int getM(int a){
    if(vis[a])
        return 0;
    vis[a]=true;
    int x=getM(to[a])+1;
    vis[a]=false;
    return x;
}
int getA(int a,int b){
    if(a==b)
        return 0;
    if(vis[a])return -1;
    vis[a]=true;
    int x=getA(to[a],b)+1;
    vis[a]=false;
    return x;
}
int main(){
    int n;
    while(scanf("%d",&n),n){
        CRT crt;
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        for(int i=1;i<=n;i++)
            scanf("%d",b+i);
        for(int i=1;i<=n;i++){
            to[a[i]]=i;
            ned[b[i]]=i;
        }
        for(int i=1;i<=n;i++){
            int M,A;
            M=getM(i);A=getA(i,ned[i]);
            if(A==-1||!crt.insert(A,M)){
                puts("-1");
                goto end;
            }
        }
        printf("%lld\n",crt.A);
        end:;
    }
    return 0;
}