Daliy Algorithm (线性dp,思维,数学)-- day 69

Nothing to fear


种一棵树最好的时间是十年前,其次是现在!

那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~

2020.4.30


人一我十, 人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

Permutation Partitions

给定一串序列 和 k

  1. 要求划分 k 个区间 {[li , ri], .. [lk,rk]}
    且 1 <= li <= ri <= k
  2. 对于每一个1 - n之间的数字确保只有唯一的一个区间
    包含他们 即 1 <= j <=n ,li <= j <=ri

对于你划分的区间你需要统计 定义的 max 值是多少
并且满足定义的max的区间的分法有多少种

首先最大值毫无疑问 是从 [n-k+1 ... n]

但是如何找到合法的方案数呢
我们找到每个区间内合法的那个数字 a1 a2 ...ak
所以在每一段相邻的部分之间
(a2-a1)(a3-a2) ... *(ak-ak-1) = ans

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
#include <cmath>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x) (x & -x)
using namespace std;
typedef long long ll;
const int MAX = 0x7ffffff;
const int mod = 998244353;
int t;

void slove()
{
	int n , k;
	cin >> n >> k;
	vector<int> a(n + 1);
	for(int i = 1;i <= n ;i ++)cin >> a[i];

	ll sum = 0;
	for(int i = 0;i < k ;i ++)sum += (n - i);
	cout << sum << " ";	
	
	ll ans = 1, pre = 0;
	for(int i = 1;i <= n ;i ++)
	{
		if(a[i] >= n - k + 1)
		{
			if(pre == 0)
			{
				 pre = i;
			}else if(pre > 0){
				ans = (ans * (i - pre) % mod) % mod;
				pre = i;
			}
		}
	}
	cout << ans << endl;
	return;
}
int main()
{
	SIS;
	slove();
}

Maximums

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
#include <cmath>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x) (x & -x)
using namespace std;
typedef long long ll;
const int MAX = 0x7ffffff;
int t;

void slove()
{
	int n;
	cin >> n;
	vector<int> b(n + 1),  a(n + 1);
	for(int i = 1;i <= n ;i ++)cin >> b[i];

	a[1] = b[1];
	int maxc = b[1];
	for(int i = 2;i <= n ;i ++)
	{
		a[i] = maxc + b[i];
		maxc = max(a[i],maxc);
	}
	for(int i = 1;i <= n ;i ++)
		cout << a[i] << " ";
	cout << endl;
	return;
}
int main()
{
	SIS;
	slove();
}

Bad Ugly Numbers

2333...3 既不能被 2 整除 又不能被 3 整除
同理还可以构造
4999...9
2777...7
...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
#include <cmath>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define lowbit(x) (x & -x)
using namespace std;
typedef long long ll;
const int MAX = 0x7ffffff;
int t;

void slove()
{
	int n;
	cin >> n;
	if(n == 1)
	{
		cout << "-1\n";
		return;
	}
	cout << "2";
	for(int i = 2;i <= n ;i ++)
	{
		cout << "3";
	}
	cout << endl;
}
int main()
{
	SIS;
	cin >> t;
	while(t--)
	{
		slove();
	}
}

luogu- P1233 木棍加工

贪心 + dp
首先要固定其中一个变量
然后对其进行降序排序
如果是在同一次准备周期里面,前面的木棍一定在后面木棍之前被加工。
这样,这个问题就转化成了在n个数中,求不下降子序列最少个数
根据dilworth定理,不下降子序列最小个数等于最大上升子序列的长度。
于是乎,问题又简化成求n个数的最大上升子序列

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int N = 5005;
int n;
struct node{
	int w, h;
}a[N];
bool cmp(node a,node b)
{
	if(a.w == b.w)
	{
		return a.h > b.h;
	}else return a.w > b.w;
}
int main()
{
	SIS;
	cin >> n;
	for(int i = 1;i <= n ;i ++)
	{
		cin >> a[i].w >> a[i].h;
	}
	// 固定一个变量进行排序。
	sort(a + 1,a + 1 + n,cmp);

	int ans = 0;
	vector<int> f(n + 1);
	for(int i = 1;i <= n ;i ++)
	{
		for(int j = 1;j < i ;j ++)
		{
			if(a[j].h < a[i].h)
			{
				f[i] = max(f[j] + 1,f[i]);
			}
		}
		ans = max(f[i] , ans);
	}
	cout << ans + 1 << endl;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/wlw-x/p/12811650.html