【Codechef】BB-Billboards

题解

传说中的……半标准杨表(行单调不增,列单调减)

如果N能整除M,我们把序列分成\(\frac{N}{M}\)

然后里面要填K个1,显然我每一段必须填K个1,且可以构造出合法的序列,所以最少要填\(K\frac{N}{M}\)个1

我们列出一个K行\(\frac{N}{M}\)列的矩阵,\((i,j)\)表示第j段第i个1填的位置,显然列是单调降的,而每行需要单调不增

这是一个半标准的杨表

公式是\(\prod_{(i,j)} \frac{r + j - i}{hook(i,j)}\)

r是值域的大小

然后我们把要乘的数和要除的数列成一个矩阵,就会发现我们会约掉很多,只剩下两边总的大小不超过\(M*K\)的矩阵

那么\(N\)不整除\(M\)呢,我们根据\(N % M\)分类一下,设\(P = N % M\)\(P < M - K\),那么我们前面\(P\)位必须都填0
如果\(P > M - K\),那么我们新增一段,每段后\(M - P\)个位置必须填1
如果\(P = M - K\),那么只有唯一的一种方案

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 2005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 + c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,M,K;
const int MOD = 1000000007;
int inv[205];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void Solve(int r,int c,int m) {
    int hr = r + c - 1,hl = r;
    int tl = m,tr = m + c - 1;
    int res = 1;
    for(int i = hl ; i < tl ; ++i) {
	for(int k = 0 ; k < r ; ++k) {
	    res = mul(res,inv[i - k]); 
	}
    }
    for(int i = hr + 1 ; i <= tr ; ++i) {
	for(int k = 0 ; k < r ; ++k) {
	    res = mul(res,i - k);
	}
    }
    out(res);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    int T;
    read(T);
    inv[1] = 1;
    for(int i = 2 ; i <= 200 ; ++i) {
	inv[i] = mul(inv[MOD % i],MOD - MOD / i); 
    }

    while(T--) {
	read(N);read(M);read(K);
	int P = N % M;
	if(P == M - K) puts("1");
	else if(P < M - K) Solve(K,N / M,M - P);
	else Solve(K - (M - P),N / M + 1,P);
    }
    return 0;
}
posted @ 2018-12-13 13:45  sigongzi  阅读(514)  评论(0编辑  收藏  举报