被3整除的子序列 (nowcoder.com)
解法:
状态表示:表示以位置
结尾,数位和模
后为
的集合
集合划分:
#include<bits/stdc++.h>
using namespace std;
const int N = 55, P = 1e9 + 7;
int f[N][3];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
int n = s.size();
s = " " + s;
for (int i = 1; i <= n; i++){
f[i][(s[i] - '0') % 3] = 1;
}
for (int i = 1; i <= n; i++){
for (int j = 0; j < 3; j++){
for (int k = i + 1; k <= n; k++){
f[k][(j + s[k] - '0') % 3] = (f[i][j] + f[k][(j + s[k] - '0') % 3]) % P;
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++) ans = (ans + f[i][0]) % P;
cout << ans;
return 0;
}
解法:
一个数如果可以被3整除,那么这个数的数位和一定可以被3整除
状态表示:表示前
个数中数位和模为
的子序列的个数
集合划分:
#include<bits/stdc++.h>
using namespace std;
const int N = 55, P = 1e9 + 7;
int f[N][3];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
f[0][(s[0] - '0') % 3] = 1;
for (int i = 1; i < s.size(); i++){
int t = (s[i] - '0') % 3;
f[i][t] = (f[i][t] + 1) % P;
for (int j = 0; j < 3; j++){
f[i][j] += (f[i - 1][j] + f[i - 1][(j + 3 - t) % 3]) % P;
}
}
cout << f[s.size() - 1][0];
return 0;
}
1010. 拦截导弹 - AcWing题库
最多能拦截的导弹数量为最长非递增子序列。
用来存每个非递增子序列的最大值,对于每个
从
数组中找到大于
的最小值
,将
的值更新为
。如果找不到
,就创建一个新的结尾为
的子序列,数组
的元素个数+1。最后答案为
数组的元素个数。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n = 1;
int a[N], f[N], g[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> a[n]) n++;
int res = 0;
for (int i = 1; i < n; i++){
f[i] = 1;
for (int j = 1; j < i; j++){
if (a[j] >= a[i]) f[i] = max(f[i], f[j] + 1);
}
res = max(f[i], res);
}
cout << res << '\n';
int cnt = 0;
for (int i = 1; i < n; i++){
int k = 0;
while (k < cnt && g[k] < a[i]) k++;
g[k] = a[i];
if (k >= cnt) cnt++;
}
cout << cnt;
return 0;
}