鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4951
題意:給一個P進制的乘法表,行和列分別代表0~p-1,第i行第j*2+1和第j*2+2列代表的是第i行的數x和第j列的數的乘積,不過這個乘法表被人弄亂了,原來的0~p-1被映射到了一個新的0~p-1的permutation(以前在CF上看見的permutation表示1~P,所以稍有迷茫),分別代表了新的不同的數,乘法表上的數也都被映射了。現在要找出映射到了什麼新的數。
思路:毫無疑問,出現最多的數一定原來是0,而(p-1)*(p-1) = p^2-2*p+1 = p*(p-2)+1,並且只有(p-1)*(p-1)時,”十位“會出現p-2,其他相乘的”十位“數字最大也只是p-3,所以對應着行列都是p-1的數的位置,”十位“代表的一定是p-2,然後遞推着找(p-1)*(p-2)的"十位"是N-3,向下找就能找到所有數字的映射了。(2進制需要特判,因爲p-2=0)
代碼:(C++過的)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-10
#define INF 0x7fffffff
#define maxn 10005
#define PI acos(-1.0)
#define seed 31//131,1313
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int a[505][1005];
int tt[505][2];
int main()
{
int T,t=0;
int M[505];
while(scanf("%d",&T))
{
t++;
if(T==0)
break;
memset(M,-1,sizeof(M));
memset(tt,0,sizeof(tt));
for(int i=0; i<T; i++)
for(int j=0; j<T; j++)
{
scanf("%d%d",&a[i][j*2+1],&a[i][j*2+2]);
tt[a[i][j*2+1]][0]++;
tt[a[i][j*2+2]][1]++;
}
printf("Case #%d:",t);
if(T==2)
{
if(tt[0][0]>tt[1][0])
printf(" 0 1\n");
else printf(" 1 0\n");
continue;
}
int all=0,pos=0;
for(int i=0; i<T; i++)
{
if(tt[i][0]+tt[i][1]>all)
{
all=tt[i][0]+tt[i][1];
pos=i;
}
}
M[0]=pos;
for(int i=0;i<T;i++)
{
if(tt[i][0]==1)
{
M[T-2]=i;
break;
}
}
for(int i=0;i<T;i++)
if(a[i][i*2+1]==M[T-2])
{
M[T-1]=i;
break;
}
for(int i=2;i<=T-1;i++)
M[T-i-1]=a[M[T-1]][2*M[T-i]+1];
for(int i=0;i<T;i++)
printf(" %d",M[i]);
printf("\n");
}
return 0;
}