ACM-ICPC Shenyang Oniste 2018 C. Insertion Sort(打表找规律)

ACM-ICPC Shenyang Oniste 2018 C. Insertion Sort

题目

问你 n 的全排列中,满足下面条件的排列有多少种。

前 k 个排序后,最长上升子序列长度至少为 n - 1。

分析

正解好像是推式子。
在这里插入图片描述

不过我想不到,,,打了个表,发现 n 一定,k 增大时的序列,做差后是个等差数列。直接把上面找出来的表模拟下出来了。

打表


#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define fuck(x) cout<<x<<endl
const int N = 1e3 + 10;
const int mod = 998244353;

vector<int> v;
int dp[100];

int f(int n, int k){
	int res = 0;
	do{
		vector<int> vv;
		vv = v;
		sort(vv.begin(), vv.begin() + k);
		int ans = 0;
		memset(dp, 0, sizeof(dp));
		dp[0] = 1;
		for(int i = 1; i < n; i++){
			int mm = -1;
			for (int j = 0; j < i; j++){
				if(vv[j] < vv[i])
					mm = max(mm, dp[j]);
			}
			dp[i] = max(0, mm) + 1;
			ans = max(dp[i], ans);
		}
		if(ans >= n-1){
			res++;
			// for(auto x : v){
			// 	printf("%d", x);
			// }
			// puts("");
		}
	} while (next_permutation(v.begin(), v.end()));
	return res;
}

void cal(int x){
	v.clear();
	for(int i = 1; i <= x; i++){
		v.push_back(i);
	}
	for(int i = 1; i <= x; i++){
		printf("%d %d %d\n", x, i, f(x, i));
	}
}


int main(){
	int x;
	scanf("%d", &x);
	cal(x);
}

代码

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define fuck(x) cout<<x<<endl
const int N = 1e3 + 10;
const int mod = 998244353;

int t;
ll n, k, q;
ll fac[N];
ll f[N], g[N];

int main(){
	scanf("%d", &t);
	for(int cas = 1; cas <= t; cas++){
		scanf("%lld%lld%lld", &n, &k, &q);
		printf("Case #%d: ", cas);
		fac[0] = fac[1] = 1;
		for(int i = 2; i < 55; i++){
			fac[i] = fac[i - 1] * i % q;
		}
		f[1] = 2 % q;		// 2 4 12 48
		for(int i = 2; i < 55; i++){
			f[i] = f[i - 1] * i % q;
		}
		for(int i = 1; i < 53; i++){
			g[i] = (fac[i + 1] - fac[i] + q) % q;
		}
		if(k > n){
			printf("%lld\n", fac[n]);
		}else{
			ll ans = fac[k];
			ll base = g[k];
			for (int i = k + 1; i <= n; i++){
				ans = (ans + base + q) % q;
				base = (base + f[k] + q) % q;
			}
			printf("%lld\n", ans);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值