50分,圆排列求调(自以为type1比较优秀)
  • 板块P8859 冒泡排序
  • 楼主ShiRoZeTsuHL卜奎BBQ!
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/11/20 15:30
  • 上次更新2023/10/27 02:13:06
查看原帖
50分,圆排列求调(自以为type1比较优秀)
678858
ShiRoZeTsuHL卜奎BBQ!楼主2022/11/20 15:30
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int maxn = 505;
int n, k, t;
int jc[maxn];
int f[maxn][maxn];

void exgcd(int a, int b, int& x, int& y) {
	if(b == 0) x = 1, y = 0;
	else exgcd(b, a%b, y, x), y -= a/b*x;
}

int P(int n, int m) {
	int x, y;
	exgcd(jc[n-m], mod, x, y);
	x = (x % mod + mod) % mod;
	return (jc[n] * x % mod + mod) % mod;
}

int C(int n, int m) {
	int x, y, z;
	exgcd(jc[m], mod, x, y);
	x = (x % mod + mod) % mod;
	exgcd(jc[n-m], mod, z, y);
	z = (z % mod + mod) % mod;
	return (jc[n] * x % mod * z % mod + mod) % mod;
}

signed main() {
//	freopen("test.in", "r", stdin);
//	freopen("test.out", "w", stdout);
	scanf("%lld %lld %lld", &n, &k, &t);
	jc[0] = 1;
	for(int i = 1; i <= n; i++)
		jc[i] = jc[i-1] * i % mod;
	
	for(int i = 0; i <= n; i++)
		f[i][0] = 1;
	
	//排列 
	if(t == 1) {
		for(int i = 2; i <= n; i++)
		for(int j = 1; j < i && j <= k; j++)
		for(int p = 0; p <= j; p++)
			f[i][j] = (f[i][j] + f[i-1-p][j-p] * P(i-1, p)) % mod;
		
		printf("%lld\n", f[n][k]);
	}
	//圆排列 
	else {
		f[1][1] = 1;
		for(int i = 2; i <= n; i++)
		for(int j = 1; j <= i && j <= k; j++) {
			if(i != n) for(int p = 1; p <= i; p++)
				f[i][j] = (f[i][j] + f[p-1][min(j-1, p-1)] * f[i-p][min(j, i-p)] % mod * C(i-1, p-1) % mod) % mod;	
			else f[i][j] = (f[i][j] + f[i-1][j-1]) % mod;
		}
		printf("%lld\n", ((f[n][k] - f[n][k-1]) % mod + mod) % mod);
 	}
	return 0;
}
2022/11/20 15:30
加载中...