Https://vijos.org/p/1286
This question cannot be captured...
First, we know that all the situations are C (n * m, K. But it is a bit difficult to solve this problem ..
The original pressure is DP .. Sigh.
Set the state f [I] [J] [k] to indicate that the placement status of row I is the solution where J places K people.
F [I] [J] [k] = sum {f [I-1] [x] [k-num [x]}, when J people do not conflict, there is no conflict between J and X. Num [x] is the number of persons in the X state.
Sum {f [N] [J] [k]} is the sum {f [N] [k]}, k is the result of the question, and J is the state of all
Obviously, this can reduce one dimension, so we can use two arrays to form a rolling array. Another thing to note is to calculate the explosion-proof precision of C (n * m, k) (because we need to divide orz and C (80, 20) by side) the number
#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 << endlinline 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;}
Background
The mid-term exam is approaching! The teacher needs HZY to help him arrange his exam seats...
Description
There are exactly n rows of M columns in the test room, and N * m candidates take the test in this test room. That is to say, all the seats have candidates. According to the school records, K candidates may cheat. Therefore, HZY cannot make any two of them sit in adjacent seats! Adjacent seats are seats in adjacent columns in the same row or in adjacent rows in the same column. HZY prepares to arrange seats in this way. First, select a random scheme. If this scheme is valid, use this scheme. Otherwise, select another one. Your task is to calculate the expected number of times that you want to select when you get a valid solution.
Format input format
The input file contains only three integers, n, m, and K.
Output Format
If there is no valid scheme, the output file seating. out should contain impossible !, Otherwise, a score P/Q is output, indicating the expected number of selections (that is, the average number of times). Here, p and q should be of mutual quality.
Example 1 input 1 [copy]
1 4 3
Sample output 1 [copy]
Impossible!
Example 2 input 2 [copy]
2 3 2
Sample output 2 [copy]
15/8
Prompt
1 ≤ n ≤ 80, 1 ≤ m ≤ 80, 1 ≤ n * m ≤ 80
0 ≤ k ≤ 20, and K ≤ n * m
[Vijos] 1286 seat schedule (pressure DP)