USACO 6.5 All Latin Squares
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的更多相关文章
- 【USACO 3.2】Magic Squares
题意 4*2个格子分别为 1234 8765 的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格. 现在给出目标状态,找出最少步数可从原始状态到达目标状态,且输 ...
- 【USACO 1.2】Palindromic Squares
进制转换,然后判断是否是回文 /******************************************* TASK: palsquare LANG: C++ Created Time: ...
- USACO Section 1.2 Palindromic Squares 解题报告
题目 题目描述 输入一个基数B,现在要从1到300之间找出一些符合要求的数字N.如果N的平方转换成B进制数之后是一个回文串,那么N就符合要求.我们将N转换成B进制数输出,然后再将N的平方转换成B进制数 ...
- USACO 完结的一些感想
其实日期没有那么近啦……只是我偶尔还点进去造成的,导致我没有每一章刷完的纪念日了 但是全刷完是今天啦 讲真,题很锻炼思维能力,USACO保持着一贯猎奇的题目描述,以及尽量不用高级算法就完成的题解……例 ...
- USACO 6.5 章节 世界上本没有龙 屠龙的人多了也便有了
All Latin Squares 题目大意 n x n矩阵(n=2->7) 第一行1 2 3 4 5 ..N 每行每列,1-N各出现一次,求总方案数 题解 n最大为7 显然打表 写了个先数值后 ...
- Project Euler 96:Su Doku 数独
Su Doku Su Doku (Japanese meaning number place) is the name given to a popular puzzle concept. Its o ...
- [转]100个经典C语言程序(益智类问题)
目录: 1.绘制余弦曲线 2.绘制余弦曲线和直线 3.绘制圆 4.歌星大奖赛 5.求最大数 6.高次方数的尾数 8.借书方案知多少 9.杨辉三角形 10.数制转换 11.打鱼还是晒网 12.抓交通肇事 ...
- 【算法】C语言趣味程序设计编程百例精解
C语言趣味程序设计编程百例精解 C/C++语言经典.实用.趣味程序设计编程百例精解(1) https://wenku.baidu.com/view/b9f683c08bd63186bcebbc3c. ...
- 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 ...
随机推荐
- 《剑指offer》 面试题53 :正则表达式匹配 Java
引言:这道题情况比较复杂,边界条件较多,为了便于以后复习,整理一下.另外,由于C语言和Java对于字符串的操作存在不一样的地方,代码也存在改动. 题目:请实现一个函数用来匹配包含'.'和'*'的正则表 ...
- 视音频数据处理入门:FLV封装格式解析
===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...
- AT1983 BBQ Hard
洛谷题目链接:BBQ Hard 题意翻译 有 n 个数对 \((A_i; B_i)\),求出 \[\sum_{i=1}^{n}\sum_{j=i + 1}^{n}{a_i+b_i+a_j+b_j ...
- alertdialog 设置最大高度
设置最大高度,有很多方法,我个人比较喜欢的是下面这种方式 ,这里的view即添加到 view.addOnLayoutChangeListener(new View.OnLayoutChangeList ...
- Django 2.0.1 官方文档翻译: 文档目录 (Page 1)
Django documentation contents 翻译完成后会做标记. 文档按照官方提供的内容一页一页的进行翻译,有些内容涉及到其他节的内容,会慢慢补上.所有的翻译内容按自己的理解来写,尽量 ...
- 手机中的js事件
// 手势事件 touchstart //当手指接触屏幕时触发 touchmove //当已经接触屏幕的手指开始移动后触发 touchend //当手指离开屏幕时触发 touchcancel // 触 ...
- Webpack的安装、配置与执行
先用npm安装 npm install webpack -g 然后在项目路径下进行项目安装 npm init # 会自动生成一个package.json文件 npm install webpack - ...
- 《大型网站SEO优化实践》学习分享
本文主要内容源自2013年阿里技术嘉年华中阿里巴巴周文君分享<大型网站SEO优化实践>.学习过后,受益匪浅,特作笔记,经常回顾吸收学习. 大型网站SEO的特点&优势&挑战 ...
- 把JS和CSS合并到1个文件
合并JS文件和CSS文件很多人都知道,也用过,目的是为了减少请求数.但有时候我们觉的把JS合并到1个文件,CSS又合并到另外1个文件也是浪费,我们如何能把CSS和JS一起合并进1个文件了? 这里需要使 ...
- 说说JavaScript中的事件模型
1.javascript中为元素添加事件处理程序的方法有以下几种方式,可以为javascript元素添加事件处理程序 (1) 直接将事件处理代码写在html中(2) 定义一个函数,赋值给html元素的 ...