blog正式转移到了这里:

http://blog.phoeagon.cz.cc



I know

phoeagon啲01世界

2009 年 2 月 21 日  星期六   晴天


~很烦很烦~【USACO latin題解】 分類: Programming Impossib...

今天遇到很不爽的事情了,然後就接著刷Usaco

USACO,latin。大概意思是要求n階(2<=n<=7)的拉丁方的數量(就是用1-n排成n*n的方陣,然後每行和每列中每個數字只能出現一次)。要求拉丁方第一行為{1,2,3,...,n}。

似乎同樣是可以簡單的cheat的,,,顯然看範圍~

BScheaters~

這道題~很囧的是,n《=6時brute force DFS仍然很快,但是n=7就嚴重TLE了~好多人都是預先跑個20s得到答案再cheat的~其實沒有必要,維基百科有答案~BSing。

主要用到一個群論的變換函數,把第一二行看做置換運算,用一個hash。

題解說的不完全是~它是用
(2,2)處填上3-n的方案完全一樣。

1. A latin square whose first row and column are both {1, 2, 3 ... N} is called a reduced (or normalized) latin square. It is useful because for any latin square, permutating its rows and columns will produce many different latin squares. Let L(K) represe
nt the number of KxK reduced latin square and N(K) represent the total number of KxK latin square, it is obvious that
N(K) = L(K) * N! * (N-1)!
since for any reduced latin square, you can permute its rows (N!) and columns ((N-1)!) and get N!*(N-1)! different latin squares. Likewise, M(K) = L(K) * (N-1)! where M(K) is the number of KxK latin square of our interest. Therefore, we only need to searc
h and count the reduced latin square.

2. For the second row (the first row is {1, 2, 3 ... N}): the number of latin square (reduced or not reduced) whose row 2 column 2 is 3 is same with number of latin square whose row 2 column 2 is 4, 5, or ... N. We can take advantage of this fact; the idea is better illustrated in the code below.

3. When we filled the kth row of a latin square (k<N), we know for a fact that the (k+1)th row could be filled. Therefore, we only need to search until N-1 row.
 

同樣用了編譯開關優化~我愛編譯開關~

 

{
TASK: latin
LANG: PASCAL
ID: awesome5
}
{$A+,B-,D-,E-,F-,G+,I-,L-,N+,O-,P+,Q-,R-,S-,T-,V-,X+,Y-}
{$ M 65520,0,655360}
//for tripley //by phoeagon //DF-search with pruning of Polya counting type sqre=array[0..7,0..7]of longint; sqrr=array[0..7,0..7]of longint; var pos,clt:sqre; row,col:sqrr; n,count,cty:longint; ct:qword; bd:longint; inde:array[0..7,0..20]of longint; procedure hash(const a:longint;var count,len:longint);inline; var v:Array[0..7]of boolean; i,curt,point,curlen:longint; begin fillchar(v,sizeof(v),0); len:=1;count:=0; for i:=1 to n do if not v[pos[a-1,i]]then begin point:=i;curt:=pos[a-1,i]; //lt:=false; inc(count);curlen:=0; while not v[curt]do begin v[curt]:=true; // begin curt:=pos[a,point]; point:=clt[a-1,curt]; //end; //lt:=lt xor true; inc(curlen); end; len:=len*curlen; end; //writeln(count,' ',len); end; {procedure prn;inline; var i,j:longint; begin writeln(count,' :'); for i:=1 to n do begin for j:=1 to n do writE(pos[i,j],' '); writeln; end; hash(2,i,j);writeln(i,' ',j); end;} procedure chg(const a,b,c,delta:longint);inline; var i:longint; begin inc(row[a,c],delta);inc(col[b,c],delta); end; procedure init;inline; var i,j:longint; begin fillchar(inde,sizeof(inde),255); reaD(n); for i:=1 to n do begin pos[1,i]:=i;clt[1,i]:=i;end; for i:=1 to n do begin pos[i,1]:=i;clt[i,1]:=i;end; for i:=1 to n do inc(row[i,i]); {for j:=2 to n do inc(toc[j,i,i]);} for j:=1 to n do inc(col[j,j]); //chg(j,i,j,1); //toc[j,i]:=toc[j,i]or(1 shl j); if n=2 then bd:=2 else bd:=n-1; end; procedure dfs(const a,b,c:longint{;const toc:sqre});inline; var i,j,x:longint;done:boolean; tmp:longint; len,cout:longint; begin done:=false; if (row[a,c]<>0)or(col[b,c]<>0) then exit; //toc[a,b]:=toc[a,b]or(1 shl c); //chg(a,b,c,1); pos[a,b]:=c;clt[a,c]:=b; chg(a,b,c,1); if (a=2)and(b=n)then begin hash(2,len,cout); //prn; //writeln(len,' ',cout,' ',c); if inde[len,cout]>=0 then begin inc(count,inde[len,cout]); //writeln('@@@:) ',inde[len,cout]); chg(a,b,c,-1); exit; end else begin tmp:=count; //writeln(inde[len,cout]); end; end; if b=n then if (a=bd) then begin inc(count);//writeln(count); //prn; //writeln(pos[3,2]); done:=true;{solution found}end else begin i:=a+1;j:=2; end else begin i:=a;j:=b+1;end; if not done then for x:=1 to n do //if toc[i,j,x]<>0 then dfs(i,j,x); //toc[a,b]:=toc[a,b]xor(1 shl c); chg(a,b,c,-1); //tmp:=0; if (a=2)and(b=n)then //if count<>tmp then begin inde[len,cout]:=count-tmp; //writeln('inde[',len,',',cout,']=',inde[len,cout]); end; end; function pw(a:longint):longint;inline; var re:longint; begin re:=1; while a>1 do begin re:=re*a; dec(a); end; exit(re); end; procedure work;inline; var x:longint; begin //for x:=1 to n do dfs(2,2,1); cty:=count;count:=0; dfs(2,2,3); count:=count*(n-2)+cty; //writeln(count); ct:=pw(n-1); //ct:=trunc(exp(ln(n-1)/ln(2))); ct:=ct*count; writeln(ct); end; begin assign(input,'latin.in');reset(input); assign(output,'latin.out');rewrite(output); init; work; close(output); end.






訪客留言 (返回 phoeagon 的日誌)

訪客名稱:
電郵地址: (不會公開)
驗證碼:  按此更新驗證碼 (如看不清楚驗證碼請點擊圖片刷新)
俏俏話: (必需 登入 後才能使用此功能)
[ 開啟多功能編輯器 ]







人氣:79313
暱稱: phoeagon
性別: 男
MORE...  
« May 2019 »
SMTWTFS
1234
567891011
12131415161718
19202122232425
262728293031
» 最新日誌
Blog Moved!
跨站jsMath实现
路由表是个好东西
Twitter Fav列表达陈100...
搞定了公式显示
» 日誌分類
全部 (175)
Code Storage (11)
Math&Phy@Chem@MM (8)
Music Anyway (5)
Programming Impossible (28)
RSS提示 (2)
StorageBox (5)
'Bout Here (12)
滑鼠人生 (42)
碎屑 (51)
未分類 (11)
» 訪客留言
最近三個月尚無任何留言
» 最近訪客
最近沒有訪客
» 每月文章
» 日誌訂閱
尚未訂閱任何日誌
» 我的好友
» 我的連結
Ink Mark --Jlim
StarKirby
|S||S||S|
「流年祭」
» 日誌統計
文章總數: 175
留言總數: 86
今日人氣: 83
累積人氣: 79313
» 站內搜索
RSS Feed