All Latin Squares

A square arrangement of numbers

1  2  3  4  5
2 1 4 5 3
3 4 5 1 2
4 5 2 3 1
5 3 1 2 4

is a 5 x 5 Latin Square because each whole number from 1 to 5 appears once and only once in each row and column.

Write a program that will compute the number of NxN Latin Squares whose first row is:

1 2 3 4 5.......N

Your program should work for any N from 2 to 7.

PROGRAM NAME: latin

INPUT FORMAT

One line containing the integer N.

SAMPLE INPUT (file latin.in)

5

OUTPUT FORMAT

A single integer telling the number of latin squares whose first row is 1 2 3 . . . N.

SAMPLE OUTPUT (file latin.out)

1344

————————————————————题解
第一行已经固定了,如果我们固定第一列为1 2 3 4 5……n 那么我们计算出的方案数乘以(n-1)!即可
然后这个优化加上位运算也只能过6。7就很尴尬了。
还有一个神一般的优化
例如
1 2 3 4 5
2 1 4 3 5
这其中有两个置换圈 1,2 和 3,4,5
如果再来一种搜索搜到了
1 2 3 4 5
2 3 1 5 4
这其中有两个置换圈 1 2 3 和 4 5
注意到了吗这个置换圈要先从大到小排序
这样的话其实这两种情况是等价的
为什么等价?
长度为2的两个圈 1 2 和 4 5可以分别一一对应
长度为3的两个圈3 4 5 和 1 2 3可以分别一一对应
也就是像我们手里得到了一张转换表,把第一种情况里的后四排的
1写成4
2写成5
3写成1
4写成2
5写成3
最后得到了一个新的拉丁方格
所以我们用一个哈希表记录置换圈的长度和所有置换圈长度的乘积,算过一遍的方案直接得出,节省很多时间……
orz反正我是想不到的
 /*
LANG: C++
PROG: latin
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define siji(i,x,y) for(int i=(x); i<=(y) ; ++i)
#define ivorysi
#define o(x) ((x)*(x))
using namespace std;
typedef long long ll;
int n;
int col[],row[],num[][];
bool v[];
ll ans,h[][];//置换圈的长度乘积,个数
void init() {
scanf("%d",&n);
siji(i,,n) {
num[][i]=i;
num[i][]=i;
col[i]=(<<i);
row[i]=(<<i);
}
memset(h,-,sizeof(h));
} ll dfs(int x,int y) {
if(x>=n){
return ;
}
ll res=;
if(x==&&y==) {
memset(v,,sizeof(v));
int cnt=,len=;
siji(i,,n) {
if(v[i]) continue;
v[i]=;
int rec=;
for(int l=num[][i];l!=i;l=num[][l]) {
v[l]=;
++rec;
}
len*=rec;
++cnt;
}
if(h[len][cnt]!=-) return h[len][cnt];
siji(i,,n) {
if(((col[y]&(<<i))==) && ((row[x]&(<<i))==)) {
col[y]|=(<<i);
row[x]|=(<<i);
num[x][y]=i;
if(y==n) res+=dfs(x+,);
else res+=dfs(x,y+);
col[y]^=(<<i);
row[x]^=(<<i);
num[x][y]=;
}
}
return h[len][cnt]=res;
}
siji(i,,n) {
if(((col[y]&(<<i))==) && ((row[x]&(<<i))==)) {
col[y]|=(<<i);
row[x]|=(<<i);
num[x][y]=i;
if(y==n) res+=dfs(x+,);
else res+=dfs(x,y+);
col[y]^=(<<i);
row[x]^=(<<i);
num[x][y]=;
}
}
return res;
}
void solve() {
init();
//if(n==7) {cout<<"12198297600"<<endl;return;}
ans=dfs(,);
siji(i,,n-) ans*=i;
printf("%lld\n",ans);
}
int main(int argc, char const *argv[])
{
#ifdef ivorysi
freopen("latin.in","r",stdin);
freopen("latin.out","w",stdout);
#else
freopen("f1.in","r",stdin);
//freopen("f1.out","w",stdout);
#endif
solve();
return ;
}

USACO 6.5 All Latin Squares的更多相关文章

  1. 【USACO 3.2】Magic Squares

    题意 4*2个格子分别为 1234 8765 的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格. 现在给出目标状态,找出最少步数可从原始状态到达目标状态,且输 ...

  2. 【USACO 1.2】Palindromic Squares

    进制转换,然后判断是否是回文 /******************************************* TASK: palsquare LANG: C++ Created Time: ...

  3. USACO Section 1.2 Palindromic Squares 解题报告

    题目 题目描述 输入一个基数B,现在要从1到300之间找出一些符合要求的数字N.如果N的平方转换成B进制数之后是一个回文串,那么N就符合要求.我们将N转换成B进制数输出,然后再将N的平方转换成B进制数 ...

  4. USACO 完结的一些感想

    其实日期没有那么近啦……只是我偶尔还点进去造成的,导致我没有每一章刷完的纪念日了 但是全刷完是今天啦 讲真,题很锻炼思维能力,USACO保持着一贯猎奇的题目描述,以及尽量不用高级算法就完成的题解……例 ...

  5. USACO 6.5 章节 世界上本没有龙 屠龙的人多了也便有了

    All Latin Squares 题目大意 n x n矩阵(n=2->7) 第一行1 2 3 4 5 ..N 每行每列,1-N各出现一次,求总方案数 题解 n最大为7 显然打表 写了个先数值后 ...

  6. Project Euler 96:Su Doku 数独

    Su Doku Su Doku (Japanese meaning number place) is the name given to a popular puzzle concept. Its o ...

  7. [转]100个经典C语言程序(益智类问题)

    目录: 1.绘制余弦曲线 2.绘制余弦曲线和直线 3.绘制圆 4.歌星大奖赛 5.求最大数 6.高次方数的尾数 8.借书方案知多少 9.杨辉三角形 10.数制转换 11.打鱼还是晒网 12.抓交通肇事 ...

  8. 【算法】C语言趣味程序设计编程百例精解

    C语言趣味程序设计编程百例精解 C/C++语言经典.实用.趣味程序设计编程百例精解(1)  https://wenku.baidu.com/view/b9f683c08bd63186bcebbc3c. ...

  9. List of NP-complete problems

    This is a list of some of the more commonly known problems that are NP-complete when expressed as de ...

随机推荐

  1. Object-C使用类静态方法创建对象时容易内存泄露

    1.所谓使用类的静态方法创建对象,就是指使用类名调用一次它的静态方法(非显式调用alloc)便可以得到一个新建的对象,比如下面两个例子: NSString* str1 = [NSString stri ...

  2. CF&&CC百套计划3 Codeforces Round #204 (Div. 1) E. Jeff and Permutation

    http://codeforces.com/contest/351/problem/E 题意: 给出一些数,可以改变任意数的正负,使序列的逆序对数量最少 因为可以任意加负号,所以可以先把所有数看作正数 ...

  3. [JSOI2007]字符加密Cipher

    bzoj 1031:[JSOI2007]字符加密Cipher Time Limit: 10 Sec  Memory Limit: 162 MB Description 喜欢钻研问题的JS同学,最近又迷 ...

  4. spring-boot添加自定义拦截器

    spring-boot中的WebMvcConfigurerAdapter类提供了很多自定义操作的方法,先贴出来大家看看 package org.springframework.web.servlet. ...

  5. 织梦dedecms 模板文件不存在,无法解析文档!

    方法一:[此对应喜欢把模板文件使用".html"的格式,] /include/arc.archives.class.php 556行 if (!preg_match("# ...

  6. 20155214 2016-2017-2 《Java程序设计》第7周学习总结

    20155214 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 UTC时间以Unix元年(1970年)为起点经过的秒数. ISO 8601并非年历系统,大部 ...

  7. HDU 1019 Least Common Multiple GCD

    解题报告:求多个数的最小公倍数,其实还是一样,只需要一个一个求就行了,先将答案初始化为1,然后让这个数依次跟其他的每个数进行求最小公倍数,最后求出来的就是所有的数的最小公倍数.也就是多次GCD. #i ...

  8. PHP在Linux下Apache环境中执行exec,system,passthru等服务器命令函数

    更多内容推荐微信公众号,欢迎关注: 若在服务器中使用php test.php运行exec,system,passthru等命令相关的脚本能成功运行,在web页面却没反应, [可能是服务器端,PHP脚本 ...

  9. UNIX环境高级编程 第9章 进程关系

    在第8章学习了进程的控制原语,通过各种进程原语可以对进程进行控制,包括新建进程.执行新程序.终止进程等.在使用fork( )产生新进程后,就出现了进程父子进程的概念,这是进程间的关系.本章更加详细地说 ...

  10. 20165230 《Java程序设计》实验四 Android程序设计实验报告

    20165230 <Java程序设计>实验四 Android程序设计实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:田坤烨 学号:20165230 成绩: 指导 ...