https://vijos.org/p/1286

这题好神不会捉。。。

首先我们知道所有情况有C(n*m, k)种,这个好搞。但是两两不相邻这个有点难搞。。

原来是状压dp。。sigh。

设状态f[i][j][k]表示第i行放置的摆放状态是j放了k个人的方案,那么有

f[i][j][k]=sum{f[i-1][x][k-num[x]]},当j的人两两不冲突,且j和x的人两两不冲突,num[x]是x状态的人的数量

最后不冲突的数目是sum{f[n][j][k]},k是题目所给的,j是所有的状态

显然这是可以减小一维的,那么我们用两个数组来组成滚动数组即可。还有一个要注意的地方就是求C(n*m, k)这个要防爆精度(因为,即我们要边乘边除orz且C(80, 20)的数量用longlong不会爆

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; } typedef long long ll;
ll f[1<<9][212][2], sum[1<<9], ans;
int n, m, k, st[1<<9], cnt;
int cal(int x) {
int ret=0;
while(x) ++ret, x-=(x&-x);
return ret;
}
ll c(ll x, ll y) {
ll ret=1; if(x-y>y) y=x-y;
for(ll i=x, j=2; i>=y+1; --i) {
ret*=i;
while(ret%j==0 && j<=x-y) ret/=j, ++j;
}
return ret;
}
ll gcd(ll a, ll b) { return b?gcd(b, a%b):a; }
int main() {
read(n); read(m); read(k);
if(m>n) swap(n, m);
int all=(1<<m)-1;
for1(i, 0, all) if(!(i&(i>>1)||(i&(i<<1)))) {
st[++cnt]=i;
sum[i]=cal(i);
f[i][sum[i]][0]=1;
}
for1(line, 2, n) {
for1(x, 1, cnt) for1(y, 1, cnt) if(!(st[x]&st[y])) {
int i=st[x], j=st[y];
for1(z, 0, k) f[i][z+sum[i]][1]+=f[j][z][0];
}
for1(x, 1, cnt) {
int i=st[x];
for1(z, 0, k)
f[i][z][0]=f[i][z][1], f[i][z][1]=0;
}
}
for1(x, 1, cnt) ans+=f[st[x]][k][0];
ll fm=c(n*m, k);
ll d=gcd(fm, ans);
if(ans) printf("%lld/%lld", fm/d, ans/d);
else puts("Impossible!");
return 0;
}

背景

快要期中考试了!老师需要hzy帮他排考试的座位。。。

描述

考场里的座位恰好有n行m列,并且恰好有n*m位考生在这个考场里面考试,也就是 说,所有的座位上都有考生。hzy根据学校记载,有k位考生可能作弊,因此hzy不能让他们之中的任何两个人做在相邻的座位上!所谓相邻的座位,即在同一 行相邻列或者在同一列的相邻行的座位。hzy准备这样安排座位,首先随机选择一种方案,如果这种方案是合法的,就用这种方案,否则重新选择。你的任务是计 算,他得到一个合法方案时,需要的期望选择次数。

格式

输入格式

输入文件为一行,仅包含三个整数n,m和k。

输出格式

如果不存在合法的方案,则输出文件seating.out中应该包含Impossible!,否则输出一个分数p/q,表示期望选择次数(即平均次数),这里p和q应该是互质的。

样例1

样例输入1[复制]

1 4 3

样例输出1[复制]

Impossible!

样例2

样例输入2[复制]

2 3 2

样例输出2[复制]

15/8

提示

1≤n≤80,1≤m≤80,1≤n*m≤80
0≤k≤20,并且k≤n*m

【vijos】1286 座位安排(状压dp)的更多相关文章

  1. vijosP1286座位安排(状压DP)

    传送门 题意 计算\(C_{n*m}^k/可行方案数\) 分析 定义dp[i][j][k]为第i行用过人数为j个且第i行状态为k的方案数 转移方程:dp[i][j][k]=Σdp[i-1][j-num ...

  2. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    [BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...

  3. bzoj1725 [Usaco2006 Nov]Corn Fields牧场的安排(状压dp)

    1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 714  Solved: 502 ...

  4. BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧 ...

  5. 2018.09.22 牧场的安排(状压dp)

    描述 农民 John 购买了一处肥沃的矩形牧场,分成M*N(1 <= M <= 12; 1 <= N <= 12)个 格子.他想在那里的一些格子中种植美味的玉米.遗憾的是,有些 ...

  6. Vijos 1456 最小总代价 (状压dp)

    看到这道题n只有16,就可以想到状压dp 每个人只有经过或者没经过,那就用1表示经过,0表示没经过 但是不是当前在谁那里,所以再加一维来记录 所以f[state][i]表示在物品在i,当前的状态是st ...

  7. 【62测试】【状压dp】【dfs序】【线段树】

    第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...

  8. BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )

    水状压dp. dp(x, s) = max{ dp( x - 1, s - {h} ) } + 奖励(假如拿到的) (h∈s). 时间复杂度O(n * 2^n) ------------------- ...

  9. 公牛与状压dp

    T1 疾病管理 裸得不能再裸的状压dp 不过数据范围骗人 考试时k==0的点没过 我也很无奈呀qwq #include<iostream> #include<cstdio> # ...

随机推荐

  1. C#秘密武器之多线程——基础

    多线程概述 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线程 ...

  2. SSL Pining Mode 设置iOS SSL 连接安全

    一:SSL Ping Mode 使用SSL来进行网络通信成为了很多mobile app的默认选择.最近一些文章发现:一些app并没有采用“额外的措施”来保证窃听不可以发生:这个“额外的步骤“就是SSL ...

  3. ubuntu14.04无法连接有线连接问题

    在windows系统下关闭有线网卡的关机,自动唤醒功能即可

  4. javascript Date日期类

      四.Date日期类 迁移时间:2017年5月27日18:43:02 Author:Marydon (一)对日期进行格式化(日期转字符串) 自定义Date日期类的format()格式化方法 方式一: ...

  5. 一个漂亮而强大的RecyclerView

    代码地址如下:http://www.demodashi.com/demo/13470.html 简介 主要提供了简单易用强大的RecyclerView库,包括自定义刷新加载效果.极简通用的万能适配器A ...

  6. [1-1] 把时间当做朋友(李笑来)Chapter 1 【心智的力量】 摘录

    今天开了读书笔记这一专题,主要是对自己今后读的书有一个小小的记录,也为解决自己读书多年的存在的一些习惯的问题. 打小就喜欢书,可能最早的书是家人买的看图识动物.还记得七八岁时见书摊上的书时赖着不走央求 ...

  7. nginx location静态文件配置

    进入nginx安装目录的conf目录下,修改nginx.conf文件,在一个server{}中添加 一个location 部分配置代码如下 root@ubuntu:/usr/local/nginx/c ...

  8. CentOS源码编译安装Nginx

    安装编译用到的软件: yum install glib2-devel openssl-devel pcre-devel bzip2-devel gzip-devel 现在到http://nginx.o ...

  9. scrapy抓取的中文结果乱码解决办法

    使用scrapy抓取的结果,中文默认是Unicode,无法显示中文. 中文默认是Unicode,如: \u5317\u4eac\u5927\u5b66 在setting文件中设置: FEED_EXPO ...

  10. 点滴积累【C#】---C#实现上传word以流形式保存到数据库和读取数据库中的word文件。

    本文修改来源:http://www.cnblogs.com/zmgdpg/archive/2005/03/31/129758.html 效果: 数据库: 思路: 首先保存word到数据库:获取上传文件 ...