2018-2019 ACM-ICPC, Asia Shenyang Regional Contest C. Insertion Sort(打表找规律)

48 篇文章 0 订阅
9 篇文章 0 订阅

C. Insertion Sort

题意:给出 n , k n,k n,k,询问 n n n的全排列中,有多少个排列在给前 k k k个元素排完序后满足最长递增子序列长度大于等于 n − 1 n-1 n1
题解:实际上好像是有公式的。但是我的做法比较蠢。打表肉眼找规律。可以发现当 k k k固定不变, n n n递增的时候是有规律的。

代码

先贴一份打表的

int dp[100];
int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	int T,n,k;
	cin >> T;
	vector<int> v;
	while(T--) {
		cin >> n >> k;
		v.clear();
		for(int i = 1; i <= n; ++i) {
			v.push_back(i);
		}
		dbg(n,k);
		int cnt = 0;
		do{
			vector<int> a = v;
			sort(a.begin(),a.begin() + k);
			for(int i = 1; i <= n; ++i) dp[i] = 1;
			for(int i = 2; i <= n; ++i) {
				for(int j = 1; j < i; ++j) {
					if(a[i - 1] > a[j - 1]) {
						dp[i] = max(dp[i], dp[j] + 1);
					}
				}
			}
			if((*max_element(dp + 1, dp + n + 1)) >= n - 1) cnt++;
		}while(next_permutation(v.begin(),v.end()));
		cout << cnt << '\n';
	}
    return 0;
}

然后是AC代码

typedef long long LL;
LL dp[100][100];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	
	int mod,n,k;
	int T,w = 0;
	cin >> T;
	while(T--) {
		cin >> n >> k >> mod;
		if(n < k) k = n;
		dp[1][1] = 1;
		dp[2][1] = 2;
		for(int i = 2; i <= n; ++i) {
			dp[i][i] = dp[i - 1][i - 1] * i % mod;
		}
		LL num = 2, sum = 0, last = 0;
		for(int j = 1; j <= k; ++j) {
			sum = (dp[j][j] + j * last % mod) % mod;
			last = sum % mod;
			num = num * j % mod;
			for(int i = j + 1; i <= n; ++i) {
				dp[i][j] = (dp[i - 1][j] % mod + sum % mod) % mod;
				sum = (sum + num) % mod;
			}
		}
		cout << "Case #" << ++w << ": " << dp[n][k] % mod << '\n';
	}

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值