12.9 矩阵变换 2859

来源:互联网 发布:cf外设淘宝店 编辑:程序博客网 时间:2024/05/29 00:34

题目

给定一个 m*n 的矩阵,每个格子里面有一颗不同颜色的宝石。再给出一些关键点,并定义两个矩阵类似为:每种颜色的宝石到各个关键点的距离和原矩阵都相同。
问有多少个矩阵和给定的矩阵类似。当然,自己和自己是类似的。
距离定义为 max{|x1-x2|,|y1-y2|}
m n 1<=m,n<=200
Key_Num 关键点的数目 0<=Key_Num<=50
接下来 Key_Num 行,每行一个二元对(i,j)表示矩阵中第 i 行第 j 列的位置是关键点。
输出一个整数。答案对 1000000009 取余后的结果。
1 6
1
1 3
答案:4
这里写图片描述

题解

令d[x,y,i]表示第x行第y列的点到第i个关键点的距离,假如对于任意0<= i< Key_Num,都有d[x,y,i]=d[x’,y’,i]成立,那么(x,y)不(x’,y’)可以分在同一组,然后对同一组的,显然可以互换,于是直接求全排列(组内元素个数的阶乘),然后丌同组之间是相互独立的,所以可以直接使用乘法原理乘在一起。作为第一题送分题,本题设了10s的时限,分组方法无论是C++的map< vector,int>这种平衡树的方法,还是hash都能轻松通过。
————来自题解
好了,那么如何hash呢(表示我只会hash)?
可以把一个点到每个关键点的距离都表示成一个<=200的数(0< n,m<=200),然后所有距离都用一个数or字符串存起来(例:点i到关键点1距离为29,到关键点2距离为352,则点i到所有2个关键点距离表示为029352),以此类推,Pascal(虽然好像有点过时)可以直接用字符串,而C++可以用longlong。

然后最简单的找到同一组所有点的方法,就是排序,然后顺序找相同点乘起来。。。。。。

感想:第一次写提高组水平(也许这题不算)的模拟赛,发现自己又要从零开始了。。orz。。就算是传说中最简单的第一题都不会。。。最可悲的是连题目都要看两三遍才能看懂,而好不容易看懂之后发现自己连暴力都不会!!!!唉,路漫漫而其修远矣!

代码

const  mo=1000000009;var  m,n,key,x,y,i,j,k:longint;  ans,s:int64;  a:array[1..200,1..200]of ansistring;  b:array[1..40001]of ansistring;function max(a,b:longint):longint;begin  if abs(a)>abs(b) then exit(abs(a)) else exit(abs(b));end;function xi(a:longint):string;var  i:longint;begin  xi:='';  while a>0 do    begin      i:=a mod 10;      a:=a div 10;      xi:=chr(i+48)+xi;    end;  while length(xi)<3 do xi:='0'+xi;end;procedure qsort(l,r:longint);var  i,j:longint;  k,t:ansistring;begin  if l>=r then exit;  i:=l;j:=r;  k:=b[(l+r) div 2];  repeat    while b[i]<k do inc(i);    while b[j]>k do dec(j);    if i<=j then      begin        t:=b[i];b[i]:=b[j];b[j]:=t;        inc(i);dec(j);      end;  until i>j;  qsort(i,r);  qsort(l,j);end;begin  readln(n,m);  readln(key);  for i:=1 to key do    begin      readln(x,y);      for j:=1 to n do        for k:=1 to m do          a[j,k]:=a[j,k]+xi(max(j-x,k-y));    end;  k:=0;  for i:=1 to n do    for j:=1 to m do      begin        inc(k);        b[k]:=a[i,j];      end;  qsort(1,k);  i:=2;ans:=1;  while i<=k do    begin      if b[i]=b[i+1] then        begin          j:=i;s:=1;          while b[j]=b[j+1] do            begin              inc(j);              s:=s*(j-i+1) mod mo;            end;          ans:=ans*s mod mo;          i:=j;        end;      inc(i);    end;  writeln(ans);end.
原创粉丝点击