Daliy Algorithm (线性dp,思维,数学)-- day 69
Nothing to fear
种一棵树最好的时间是十年前,其次是现在!
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.4.30
人一我十, 人十我百,追逐青春的梦想,怀着自信的心,永不言弃!
Permutation Partitions
给定一串序列 和 k
- 要求划分 k 个区间 {[li , ri], .. [lk,rk]}
且 1 <= li <= ri <= k - 对于每一个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;
}