A 2025年新年农场计划

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 10005
#define inf 0x3f3f3f3f-1

int tot;
int d[N];
int cnt=1;
int dis[N];
int head[N];
int n,m,s,t;

struct Edge{
    int to,nxt,flow;
}edge[4400000];

void add(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].nxt=head[x];
    edge[cnt].flow=z;
    head[x]=cnt;
}

bool bfs(){
    memset(d,0,sizeof d); d[s]=1;
    std::queue<int> q; q.push(s);
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=edge[i].nxt){
            int to=edge[i].to;
            if(!edge[i].flow) continue;
            if(d[to]) continue;
            d[to]=d[u]+1;
            q.push(to);
            if(to==t) return 1;
        }
    }
    return 0;
}

int dinic(int now,int flow){
    if(now==t) return flow;
    int rest=flow;
    for(int i=head[now];i;i=edge[i].nxt){
        if(!rest) return flow;
        int to=edge[i].to;
        if(!edge[i].flow) continue;
        if(d[to]!=d[now]+1) continue;
        int k=dinic(to,std::min(rest,edge[i].flow));
        if(!k) d[to]=0;
        rest-=k;
        edge[i].flow-=k;
        edge[i^1].flow+=k;
    }
    return flow-rest;
}

signed main(){
    scanf("%d",&n); s=n+1; t=s+1;
    for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(s,i,x),add(i,s,0);
    for(int x,i=1;i<=n;i++) scanf("%d",&x),tot+=x,add(i,t,x),add(t,i,0);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        int T,tota,totb;
        scanf("%d%d%d",&T,&tota,&totb);
        tot+=tota+totb;
        add(s,n+2+i,tota); add(n+2+i,s,0);
        add(n+2+i+m,t,totb); add(t,n+2+i+m,0);
        for(int x,j=1;j<=T;j++){
            scanf("%d",&x);
            add(n+2+i,x,inf);
            add(x,n+2+i,0);
            add(x,n+2+i+m,inf);
            add(n+2+i+m,x,0);
        }
    }
    int maxflow=0,flow=0;
    while(bfs()) 
        while(flow=dinic(s,0x3f3f3f3f)) maxflow+=flow;
    printf("%d\n",tot-maxflow);
    return 0;
}

B 上次铺瓷砖这次装小路??

这是一个典型的动态规划问题,类似于完全背包问题。定义 dp[j] 为覆盖 j 米所需的最小费用。初始时,dp[0] = 0(覆盖 0 米不需要费用),其余初始化为无穷大。对于每个长度 j,遍历所有可能的彩灯长度 i(1 到 n),若 j >= i,则更新状态:

dp[j] = min(dp[j], dp[j-i] + sum[i])。

最终答案即为 dp[m]。

#include <bits/stdc++.h>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    vector<int> sum(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> sum[i];
    }
    vector<int> dp(m + 1, INT_MAX);
    dp[0] = 0;
    for (int j = 1; j <= m; ++j) {
        for (int i = 1; i <= n; ++i) {
            if (i <= j && dp[j - i] != INT_MAX) {
                dp[j] = min(dp[j], dp[j - i] + sum[i]);
            }
        }
    }
    cout << (dp[m] == INT_MAX ? -1 : dp[m]) << endl;
    return 0;
}

C 乘法逆元

逆元基础

#include <bits/stdc++.h>
using namespace std;

int n, p, inv[3000005];

void write(int x) {
    if (x > 9) write(x / 10);
    putchar(x % 10 ^ 48);
}
int main() {
    cin >> n >> p;
    inv[1] = 1;
    for (int i = 2; i <= n; i++) inv[i] = 1ll * (p - p / i) * inv[p % i] % p;
    for (int i = 1; i <= n; i++) write(inv[i]), putchar(10);
}

D ZL的零食

操作1 的话就区间维护最小值,这个最小值是为了操作2的输出

然后再维护一个标记,表示这个区间要最小变成x,所以这个标记要取最大值

操作2就维护一个堆,类似NOI2005超级钢琴的堆

在给定区间[ l , r ] 内先查一个最小值,设这个最小值的位置为p

那么我们还需要查询[ 1 , p - 1 ]和[ p + 1 , r ]内的最小值

这样找到所要求的x 个最小值就可以了

用一个优先队列实现,只要够了x个元素就可以break

因为先出来的元素一定比后出来的元素小

所以线段树还需要维护区间最小值的位置

#include <bits/stdc++.h>
#define A 2000010

using namespace std;
typedef long long ll;
struct node {
	int l, r, w, f, p;
	friend bool operator < (const node a, const node b) {
		return a.w > b.w;
	}
}tree[A];
void up(int k) {
	tree[k].w = INT_MAX;
	if (tree[k << 1].w < tree[k].w) tree[k].w = tree[k << 1].w, tree[k].p = tree[k << 1].p;
	if (tree[k << 1 | 1].w < tree[k].w) tree[k].w = tree[k << 1 | 1].w, tree[k].p = tree[k << 1 | 1].p;
}
int n, w[A], m, opt, a, b, k, x, sta[A], top;
priority_queue<node> q;
void build(int k, int l, int r) {
	tree[k].l = l; tree[k].r = r;
	if (l == r) {tree[k].w = w[l]; tree[k].p = l; return;}
	int m = (l + r) >> 1;
	build(k << 1, l, m);
	build(k << 1 | 1, m + 1, r);
	up(k);
}
void down(int k) {
	tree[k << 1].f = max(tree[k << 1].f, tree[k].f);
	tree[k << 1 | 1].f = max(tree[k << 1 | 1].f, tree[k].f);
	tree[k << 1].w = max(tree[k << 1].w, tree[k].f);
	tree[k << 1 | 1].w = max(tree[k << 1 | 1].w, tree[k].f);
	tree[k].f = 0;
}
void change(int k, int l, int r, int val) {
	if (tree[k].l >= l and tree[k].r <= r) {
		tree[k].w = max(tree[k].w, val);
		tree[k].f = max(tree[k].f, val);
		return;
	}
	if (tree[k].f) down(k);
	int m = (tree[k].l + tree[k].r) >> 1;
	if (l <= m) change(k << 1, l, r, val);
	if (r > m) change(k << 1 | 1, l, r, val);
	up(k);
}
pair<int, int> ask(int k, int l, int r) {
	if (tree[k].l >= l and tree[k].r <= r) return make_pair(tree[k].w, tree[k].p);
	if (tree[k].f) down(k);
	int m = (tree[k].l + tree[k].r) >> 1; pair<int, int> ans = make_pair(INT_MAX, 0);
	if (l <= m) {
		pair<int, int> p = ask(k << 1, l, r);
		if (p.first < ans.first) ans = p;
	}
	if (r > m) {
		pair<int, int> p = ask(k << 1 | 1, l, r);
		if (p.first < ans.first) ans = p;
	}
	return ans;
}

int main(int argc, char const *argv[]) {
	cin >> n;
	for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
	build(1, 1, n); cin >> m;
	while (m--) {
		scanf("%d%d%d%d", &opt, &a, &b, &k);
		if (opt == 1) change(1, a, b, k);
		else {
			scanf("%d", &x); top = 0;
			while (!q.empty()) q.pop();
			pair<int, int> p = ask(1, a, b);
			q.push(node{a, b, p.first, 0, p.second});
			while (!q.empty()) {
				node fr = q.top(); q.pop();
				if (fr.w >= k) continue;
				sta[++top] = fr.w;
				pair<int, int> p1 = ask(1, fr.l, fr.p - 1), p2 = ask(1, fr.p + 1, fr.r);
				q.push(node{fr.l, fr.p - 1, p1.first, 0, p1.second});
				q.push(node{fr.p + 1, fr.r, p2.first, 0, p2.second});

				if (top == x) break;
			}

			if (top != x) puts("-1");
			else {
				sort(sta + 1, sta + top + 1);
				for (int i = 1; i <= top; i++) printf("%d ", sta[i]); puts("");
			}
		}
	}
	return 0;
}

E 2025新年祝福语生成器

def calculate_min_heartvalue(s: str, t: str) -> int:
    if len(s) != len(t):
        return -1
    
    n = len(s)
    heart_value = 0
    
    # 检查每个位置
    for i in range(n):
        if s[i] != t[i]:
            # 如果字符不同且都是字母,需要使用通配符
            if s[i].isalpha() and t[i].isalpha():
                heart_value += 1  # 替换为'*'的成本
            else:
                # 如果包含数字且不同,无法转换
                return -1
    
    return heart_value

# 读取输入
s = input().strip()
t = input().strip()

# 计算并输出结果
result = calculate_min_heartvalue(s, t)
print(result)

F 小露似乎很喜欢7

签到题

n = int(input())
summ = 0
a = input().split()
for i in a:
    if '7' in i:
        ii = int(i)
        summ += ii
    else:
        ii = int(i)
        if ii % 7 == 0:
            summ += ii
print(summ)