A
题意:从区间[1, n]任取一个数x,从区间[1, m]任取一个数y。问你有多少对(x, y)满足(x + y) % 5 == 0。
思路:5个一循环。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <string>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e6 + 10;
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF) {
LL ans = 0;
for(int i = 1; i <= min(n, 5); i++) {
for(int j = 1; j <= m; j++) {
if((i + j) % 5 == 0) {
ans++;
}
}
}
ans = 1LL * n / 5 * ans;
n %= 5;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if((i + j) % 5 == 0) {
ans++;
}
}
}
printf("%lld\n", ans);
}
return 0;
}
题意:给定n个数,你可以将任意一个数减少到1。对于最后得到的序列,问你最大的没有出现的数。
思路:怕错,套了个二分,最后发现想复杂了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <string>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
int a[MAXN];
int num[MAXN], sum[MAXN];
int n;
bool judge(int N) {
int have = sum[n] - sum[N-1];
for(int i = N-1; i >= 1; i--) {
have += num[i];
have--;
if(have < 0) return false;
}
return true;
}
int main()
{
while(scanf("%d", &n) != EOF) {
CLR(num, 0);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if(a[i] > n) a[i] = n;
num[a[i]]++;
}
sum[0] = 0;
for(int i = 1; i <= n; i++) {
sum[i] = sum[i-1] + num[i];
}
int l = 1, r = n + 1, ans;
while(r >= l) {
int mid = (l + r) >> 1;
if(judge(mid)) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
printf("%d\n", ans);
}
return 0;
}
节点v是bad:v的子树下存在一个节点u使得dist(u, v) > val[u]。
题意:给定一颗树,树边的权值以及每个节点的价值。问最少去掉多少个节点使得树中不存在bad节点。
思路:对于节点u而言,若dist(root, u) - min(dist(root, v)) (其中v是root到u路径上所经过的所有节点)> val[u]说明需要去掉u以及u的子树。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <string>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
struct Edge {
int from, to, val, next;
};
Edge edge[MAXN * 2];
int head[MAXN], edgenum;
void init() { CLR(head, -1); edgenum = 0; }
void addEdge(int u, int v, int w) {
Edge E = {u, v, w, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
int val[MAXN], son[MAXN];
bool vis[MAXN];
void DFS(int u, int fa, LL sum, LL Min) {
if(sum - Min > val[u]) {
vis[u] = true;
return ;
}
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(v == fa) continue;
DFS(v, u, sum + edge[i].val, min(Min, sum + edge[i].val));
}
}
void DFS1(int u, int fa) {
son[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if(v == fa) continue;
DFS1(v, u);
son[u] += son[v];
}
}
int main()
{
int n;
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &val[i]); vis[i] = false;
}
init();
for(int i = 1; i < n; i++) {
int u, w; scanf("%d%d", &u, &w);
addEdge(i+1, u, w);
addEdge(u, i+1, w);
}
DFS(1, -1, 0, 0); DFS1(1, -1);
int ans = 0;
for(int i = 1; i <= n; i++) {
if(vis[i]) {
ans += son[i];
}
}
printf("%d\n", ans);
}
return 0;
}
题意:给定两个字符串a和b,你可以把它们分割k次,并选择若干个相等且顺序相同的段。问你选择段的最大长度和。
思路:
dp[i][j][k][1]
表示处理
a[1]−a[i]
、
b[1]−b[j]
分割
k
次且选择的最后一段以
dp[i][j][k][0]
表示处理
a[1]−a[i]
、
b[1]−b[j]
分割
k
次的最优解。
把
a[i]
、
b[j]
直接加到最后一个合法段,或者当做独立段的开头。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <string>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e3 + 10;
int dp[MAXN][MAXN][11][2];
char a[MAXN], b[MAXN];
int main()
{
int n, m, k;
while(scanf("%d%d%d", &n, &m, &k) != EOF) {
scanf("%s", a+1); scanf("%s", b+1);
int la = strlen(a+1); int lb = strlen(b+1);
CLR(dp, 0);
for(int i = 1; i <= la; i++) {
for(int j = 1; j <= lb; j++) {
if(a[i] == b[j]) {
for(int p = 1; p <= k; p++) {
dp[i][j][p][1] = max(dp[i][j][p][1], 1 + max(dp[i-1][j-1][p][1], dp[i-1][j-1][p-1][0]));
}
}
for(int p = 1; p <= k; p++) {
dp[i][j][p][0] = max(dp[i][j][p][0], max(dp[i][j][p][1], max(dp[i-1][j][p][0], dp[i][j-1][p][0])));
}
}
}
printf("%d\n", dp[la][lb][k][0]);
}
return 0;
}