Hdu 4951 Multiplication table

题目链接

Multiplication table

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 491    Accepted Submission(s): 230


Problem Description
Teacher Mai has a multiplication table in base p.

For example, the following is a multiplication table in base 4:

* 0 1 2 3
0 00 00 00 00
1 00 01 02 03
2 00 02 10 12
3 00 03 12 21

But a naughty kid maps numbers 0..p-1 into another permutation and shuffle the multiplication table.

For example Teacher Mai only can see:

1*1=11 1*3=11 1*2=11 1*0=11
3*1=11 3*3=13 3*2=12 3*0=10
2*1=11 2*3=12 2*2=31 2*0=32
0*1=11 0*3=10 0*2=32 0*0=23

Teacher Mai wants you to recover the multiplication table. Output the permutation number 0..p-1 mapped into.

It's guaranteed the solution is unique.
 

Input
There are multiple test cases, terminated by a line "0".

For each test case, the first line contains one integer p(2<=p<=500).

In following p lines, each line contains 2*p integers. The (2*j+1)-th number x and (2*j+2)-th number y in the i-th line indicates equation i*j=xy in the shuffled multiplication table.

Warning: Large IO!
 

Output
For each case, output one line.

First output "Case #k:", where k is the case number counting from 1. The following are p integers, indicating the permutation number 0..p-1 mapped into.
 

Sample Input
   
   
   
   
4 2 3 1 1 3 2 1 0 1 1 1 1 1 1 1 1 3 2 1 1 3 1 1 2 1 0 1 1 1 2 1 3 0
 

Sample Output
   
   
   
   
Case #1: 1 3 2 0
题意:对于一个p进制的乘法表。现在将p进制的0,1,2....p-1映射成0到p-1的另一个排列,并且将乘法表0到p-1的相对顺序打乱。现在给你打乱以后的乘法表,让你求出每个数映射成了那个数?
题解:解法很简单,但是不容易想到。首先0可以很容易确定出来,因为乘法表中只有0的那一行和那一列全是0。对于剩下的数字,1对于的那行十位只会出现0。对于2对应的那行,十位只会出现0,1,并且都会出现。那么对于i对应的那行,十位只会出现0,1,,,i-1,并且都会出现。简单的证明一下,对于第i行,十位最大是i*(p-1)那个数,显然是i-1,最小显然是0,由于i<p,所以对于0到i-1的每一个十位,都会出现。代码如下:(由于题目提示输入数据很多,所以用了输入输出优化)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#define nn 550
using namespace std;
pair<int,int> a[nn][nn];
map<int,int>ma;
int p;
bool use[nn];
inline int read()
{
    char ch;
    bool flag=false;
    int re=0;
    while(!(((ch=getchar())>='0'&&(ch<='9'))||(ch=='-')));
    if(ch!='-')
    {
        re*=10;
        re+=ch-'0';
    }
    else
        flag=true;
    while((ch=getchar())>='0'&&(ch<='9'))
    {
        re*=10;
        re+=ch-'0';
    }
    if(flag)
        re=-re;
    return re;
}
inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>=10)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}
int main()
{
    int i,j;
    int cas=1;
    while(1)
    {
        p=read();
        if(p==0)
            break;
        ma.clear();
        for(i=0;i<p;i++)
        {
            for(j=0;j<p;j++)
            {
                a[i][j].first=read();
                a[i][j].second=read();
            }
        }
        printf("Case #%d: ",cas++);
        for(i=0;i<p;i++)
        {
            for(j=0;j<p;j++)
            {
                if(a[i][j].first!=a[i][j].second)
                    break;
                if(j&&a[i][j]!=a[i][j-1])
                    break;
            }
            if(j==p)
            {
                ma[0]=i;
                break;
            }
        }
        int ix;
        for(i=0;i<p;i++)
        {
            if(ma[0]==i)
                continue;
            memset(use,false,sizeof(use));
            for(j=0;j<p;j++)
            {
                use[a[i][j].first]=true;
            }
            ix=0;
            for(j=0;j<p;j++)
            {
                if(use[j])
                    ix++;
            }
            ma[ix]=i;
        }
        for(i=0;i<p;i++)
        {
            write(ma[i]);
            printf("%c",i==p-1?'\n':' ');
        }

    }
    return 0;
}


你可能感兴趣的:(ACM)