遍历每个数,若该数大于 ans 的末尾元素,直接加入;否则,用该数替换
ans 中第一个大于等于它的元素。
最终 ans 的长度即为最长上升子序列的长度。
关键点:贪心策略结合二分查找优化时间复杂度到 O(n log n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<bits/stdc++.h> usingnamespace std; int n, x; vector<int> ans; intmain(){ cin >> n; for (int i = 1; i <= n; i++) { cin >> x; if (ans.empty() || ans.back() < x) { ans.push_back(x); } else { int idx = lower_bound(ans.begin(), ans.end(), x) - ans.begin(); // cout << idx << endl; ans[idx] = x; } } cout << ans.size(); return0; }
1 2 3 4 5 6 7 8 9 10 11 12 13
import bisect
n = int(input()) m = list(map(int, input().split())) a = [] for x in m: pos = bisect.bisect_left(a, x) if pos == len(a): a.append(x) elif a[pos] > x: a[pos] = x # 仅当 a[pos] > x 时才替换(去重)
#include<bits/stdc++.h> usingnamespace std; int n,m; constint N = 1e2+9,M = 1000000007; int f[N][N][N]; intmain() { cin>>n>>m; f[0][0][2] = 1; for(int i = 0;i<=n;i++) { for(int j = 0;j<=m;j++) { for(int k = 0;k<=m;k++) { int &val = f[i][j][k]; if(i&&k%2==0) val = (val+f[i-1][j][k/2])%M; if(j) val = (val+f[i][j-1][k+1])%M; } } } cout<<f[n][m-1][1]; return0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
MOD = 10**9 + 7 n, m = map(int, input().split()) f = [[[0]*(m+2) for _ inrange(m+1)] for __ inrange(n+1)] f[0][0][2] = 1
for i inrange(n+1): for j inrange(m+1): for k inrange(m+1): if i > 0and k % 2 == 0: f[i][j][k] = (f[i][j][k] + f[i-1][j][k//2]) % MOD if j > 0and k + 1 <= m: f[i][j][k] = (f[i][j][k] + f[i][j-1][k+1]) % MOD
#include<bits/stdc++.h> usingnamespace std; /* 数论 + 背包 n 种蒸笼,每个可以放 ai 个包子,蒸笼的数量是无限的 求有哪些 A 不能被 a1 * x1 + a2 * x2 + ai * xi + ... + an * xn 表示出来 最简单的情况是两数之和为给定两个种蒸笼 a,b 其可以组合出:ax + by = m 形式符合裴蜀定理,但要注意的是本题中 x,y 不能为负数,因此即使 gcd(ai) = 1 也不说明所有的整数都能被组合出来 */ int n, ans, flg = 0; // 初始化为 0 避免对结果造成影响 constint N = 1e2+9, M = 1e5+9;
int a[N]; bool dp[M]; intgcd(int a, int b){ if (b == 0)return a; returngcd(b, a % b); }
intmain(){ cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; // flg = __gcd(flg,a[i]); flg = gcd(flg, a[i]); } if (flg != 1) { // 说明 ai 中的数字不是互质的,则必定有一些质数及它们的倍数无法被描述,因此无法被组合的数字个数为无限 cout << "INF"; } else { dp[0] = 1; // 初始化,默认 0 个包子是可以被组合出来的 // 枚举所有的数字 for (int i = 0; i < n; i++) { for (int j = a[i]; j < M; j++) { if (dp[j - a[i]])dp[j] = 1; } } for (int i = 0; i < M; i++) { if (!dp[i])ans++; } cout << ans; } return0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import math
n = int(input()) a = [int(input()) for _ inrange(n)] gcd_all = a[0] for num in a[1:]: gcd_all = math.gcd(gcd_all, num)
if gcd_all != 1: print("INF") else: max_val = 10**5 dp = [False]*(max_val + 1) dp[0] = True for num in a: for j inrange(num, max_val + 1): if dp[j - num]: dp[j] = True print(sum(not x for x in dp[1:max_val + 1]))