当前位置: 首页 > news >正文

2025.5.26【ZR NOI模拟赛 T2】草莓函数 题解(性质,二分图最大权匹配)

算是比较好玩的题吧,虽然感觉不太可能考。
但是我考试时真是一点思路都没有啊啊啊啊啊啊。。。。
记录一下。

题意

给定 n n n 对整数 ( x i , y i ) (x_i, y_i) (xi,yi) 和一个整数 C C C,求一个定义域和值域都是 Z \Z Z 的函数 f ( x ) f(x) f(x),满足 ∀ x ∈ Z \forall x \in \Z xZ f ( x ) + C = f ( 2 f ( x ) − x + 1 ) f(x) + C = f(2f(x) - x + 1) f(x)+C=f(2f(x)x+1),使得 ∑ i = 1 n ∣ f ( x i ) − y i ∣ \sum\limits_{i = 1}^{n}|f(x_i) - y_i| i=1nf(xi)yi 最小。

1 ≤ n ≤ 10 4 , 1 ≤ C ≤ 200 , 1 ≤ x i , y i ≤ 10 9 1 \leq n \leq 10^4, 1 \leq C \leq200, 1 \leq x_i, y_i \leq 10^9 1n104,1C200,1xi,yi109

分析

首先要明白这个函数取最优可能是没有解析式的。因为假设有解析式那么这个函数只能是 1 1 1 次函数,并且 k = 1 , b = C − 1 2 k = 1, b = \frac{C - 1}{2} k=1,b=2C1。然后你会发现 C C C 是偶数的时候你甚至构造不出来一个合法的一次函数满足值域是 Z \Z Z。然后就倒闭了。。

那么我们将它理解成 你要给每个 f ( x ) f(x) f(x) 赋一个值,满足上述限制,并且使所求式最小

那么怎样赋值才能满足限制呢?先来对函数推一些性质。

性质: ∀ x ∈ Z , f ( x + 2 C ) = f ( x ) + 2 C \forall x \in Z, f(x + 2C) = f(x) + 2C xZ,f(x+2C)=f(x)+2C
证明:
f ( x ) = t f(x) = t f(x)=t,有 t + C = f ( 2 t − x + 1 ) t + C = f(2t - x + 1) t+C=f(2tx+1)
迭代: f ( 2 t − x + 1 ) + C = f ( 2 ( t + C ) − ( 2 t − x + 1 ) + 1 ) = f ( x + 2 C ) f(2t - x + 1) + C = f(2(t + C) - (2t - x + 1) + 1) = f(x + 2C) f(2tx+1)+C=f(2(t+C)(2tx+1)+1)=f(x+2C)
所以 f ( x + 2 C ) = t + 2 C = f ( x ) + 2 C f(x + 2C) = t + 2C = f(x) + 2C f(x+2C)=t+2C=f(x)+2C
得证。

因此如果将 x % 2 C x \% 2C x%2C 相同的 x x x 分到同一类,那么只有一类里定了一个数的 f ( x ) f(x) f(x),其它的 f ( x ) f(x) f(x) 也都随之确定,并且斜率为 1 1 1

不妨考虑确定 x ∈ [ 0 , 2 C ) x \in [0,2C) x[0,2C) 的所有 f ( x ) f(x) f(x),但是这些值是可以任意定的吗?
考虑如果定下了一个 f ( x ) = t f(x) = t f(x)=t,那么 2 t − x + 1 2t - x + 1 2tx+1 所在那一类也一定会被确定。根据刚才的性质,从 x x x 的等价类出发迭代两次还会回到 x x x 的等价类上。因此再往后迭代一次确定的点所在等价类就是 x , 2 t − x + 1 , x , 2 t − x + 1 , … x, 2t - x + 1, x, 2t - x + 1,\dots x,2tx+1,x,2tx+1,。我们发现它们形成了一个闭环,因此限制就完全转化成了每次同时确定两个等价类,其余等价类迭代一次都不能跑到这两个等价类上。这相当于一个 匹配模型

观察到 C C C 比较小,所以等价类的数量很少。因此我们有一个初步思路:计算两个等价类 x , y x, y x,y 匹配所产生的最小代价 w ( x , y ) w(x, y) w(x,y),然后在 x , y x, y x,y 之间连一条权值为 w ( x , y ) w(x, y) w(x,y) 的边,最后跑一遍 最小权完美匹配 即可。
这里的 w ( x , y ) w(x, y) w(x,y) 是指确定 x , y x, y x,y 两个等价类的每个点值后对所求式子的最小贡献。

但是这是 一般图最小权最大匹配一般图最大匹配 都需要用 带花树 才能做。这是我们不可能会的科技。

接着推一下式子:
f ( x ) = t f(x) = t f(x)=t,那么 f ( 2 t − x + 1 ) = t + C f(2t - x + 1) = t + C f(2tx+1)=t+C
我们注意到 x + ( 2 t − x + 1 ) = 2 t + 1 x + (2t - x + 1) = 2t + 1 x+(2tx+1)=2t+1 是奇数,并且 ( 2 t − x + 1 ) % 2 C (2t -x+1) \% 2C (2tx+1)%2C 不会改变 2 t − x + 1 2t - x + 1 2tx+1 的奇偶性,因此 x x x 只会和一个与它奇偶性不同的等价类匹配!!

那么问题就变成了 二分图最小权最大匹配,只需要 E K EK EK最小费用最大流 即可。

最后剩下一个问题,如何求 w ( x , y ) w(x, y) w(x,y)
首先设 a a a 的等价类中包含 m m m { ( x i , y i ) } \{(x_i, y_i)\} {(xi,yi)},满足 x i % 2 C = a x_i \% 2C = a xi%2C=a
x i = k i × 2 C + a x_i = k_i \times 2C + a xi=ki×2C+a,那么有:
∑ i = 1 m ∣ f ( x i ) − y i ∣ = ∑ i = 1 m ∣ f ( k i × 2 C + a ) − y i ∣ = ∑ i = 1 m ∣ f ( a ) + k i × 2 C − y i ∣ = ∑ i = 1 m ∣ f ( a ) − ( y i − k i × 2 C ) ∣ \sum\limits_{i = 1}^{m}|f(x_i) - y_i| = \sum\limits_{i = 1}^{m}|f(k_i \times 2C + a) - y_i| = \sum\limits_{i = 1}^{m}|f(a) + k_i \times 2C -y_i| = \sum\limits_{i = 1}^{m}|f(a) - (y_i - k_i \times 2C)| i=1mf(xi)yi=i=1mf(ki×2C+a)yi=i=1mf(a)+ki×2Cyi=i=1mf(a)(yiki×2C)

这看起来像是数轴上选一个点到其它点的距离和最小,结论是选中位数最优。
但是由于 f ( x ) f(x) f(x) 的选择后要匹配上 y y y,因此还要列一些关系式:

f ( x ) = t f(x) = t f(x)=t,则 2 t − x + 1 ≡ y ( m o d 2 C ) 2t - x + 1 \equiv y \pmod {2C} 2tx+1y(mod2C)
2 t − x + 1 = y + 2 n C ( n ∈ Z ) 2t - x + 1 = y + 2nC(n \in \Z) 2tx+1=y+2nC(nZ)
t = n C + x + y − 1 2 ( n ∈ Z ) t = nC + \frac{x + y - 1}{2}(n \in \Z) t=nC+2x+y1(nZ)
f ( x ) = n C + x + y − 1 2 ( n ∈ Z ) f(x) = nC + \frac{x + y - 1}{2}(n \in \Z) f(x)=nC+2x+y1(nZ)

这相当于初始 f ( x ) f(x) f(x) x + y − 1 2 \frac{x + y - 1}{2} 2x+y1,你可以朝左右跳任意步,步长为 C C C。那么显然还是跳到中位数附近 O ( 1 ) O(1) O(1) 个位置取到最优。

但是别忘了 t t t 的赋值同样影响着 y y y 等价类的贡献,我们来看看 f ( y ) f(y) f(y) 的表达式:
f ( 2 t − x + 1 ) = t + C f(2t - x + 1) = t +C f(2tx+1)=t+C
f ( y + 2 n C ) = f ( y ) + 2 n C = t + C = n C + x + y − 1 2 + C f(y + 2nC) = f(y) + 2nC = t + C = nC + \frac{x + y - 1}{2} + C f(y+2nC)=f(y)+2nC=t+C=nC+2x+y1+C
f ( y ) = x + y − 1 2 + C − n C f(y) = \frac{x + y - 1}{2} + C - nC f(y)=2x+y1+CnC
f ( y ) + f ( x ) = x + y + C − 1 f(y) + f(x) = x + y + C - 1 f(y)+f(x)=x+y+C1 f ( y ) = ( x + y + C − 1 ) − f ( x ) f(y) = (x + y + C - 1) - f(x) f(y)=(x+y+C1)f(x)

然后变量就被化成一个了。我们将 f ( y ) f(y) f(y) 带入它的贡献式:

∑ i = 1 m y ∣ f ( y ) − ( y i − k i × 2 C ) ∣ = ∑ i = 1 m y ∣ f ( x ) − ( x + y + C − 1 − ( y i − k i × 2 C ) ) ∣ \sum\limits_{i = 1}^{m_y}|f(y) - (y_i - k_i \times 2C)| = \sum\limits_{i = 1}^{m_y}|f(x) - (x+y+C - 1 -(y_i - k_i \times 2C))| i=1myf(y)(yiki×2C)=i=1myf(x)(x+y+C1(yiki×2C))

那么只需要将 y y y 等价类中的点 ( x i , y i ) (x_i, y_i) (xi,yi) x + y + C − 1 − ( y i − k i × 2 C ) x + y + C - 1 - (y_i - k_i \times 2C) x+y+C1(yiki×2C) 也加入数轴中,求出最优位置即可。
每次只有 O ( 1 ) O(1) O(1) 个位置需要 c h e c k check check,每个等价类中的点一共被枚举 C C C 次,总复杂度 O ( n C ) O(nC) O(nC)

总复杂度 O ( n C + 费用流复杂度 ) O(nC + 费用流复杂度) O(nC+费用流复杂度),可过。

CODE:

// 最小费用最大流 
#include<bits/stdc++.h>
#define pb emplace_back
using namespace std;
const int N = 1e4 + 10;
const int M = 210;
const int INF = 1e8;
typedef long long LL;
int n, C, len;
LL x[N], y[N], w[M * 2][M * 2];
LL num[N];
vector< int > node[M * 2];
inline LL calc(LL x) {LL ret = 0;for(int i = 1; i <= len; i ++ ) ret += abs(num[i] - x);return ret;
}
inline LL up(LL x, int s) {if(s >= x) return s - (s - x) / C * C;else return s + ((x - s - 1) / C + 1) * C;
}
inline LL down(LL x, int s) {LL p = up(x, s);if(p == x) return p;else return p - C;
}
inline LL solve(int a, int b) { // f(a) 应取中位数 len = 0; for(auto v : node[a]) num[++ len] = (y[v] - (x[v] - a));for(auto v : node[b]) num[++ len] = (a + b + C - 1 - (y[v] - (x[v] - b)));sort(num + 1, num + len + 1);int p = (len + 1) / 2; LL res = 2e18;for(int i = p; i <= ((len & 1) ? p : p + 1); i ++ ) {if(i > len) break;if((len & 1) || (i == p + 1)) res = min(res, calc(down(num[i], (a + b - 1) / 2)));if((len & 1) || (i == p)) res = min(res, calc(up(num[i], (a + b - 1) / 2)));}return res;
}
int S, T, nd[M * 2], idx, pre[M * 2];
LL incf[M * 2], d[M * 2];
struct edge {int v, last, c; LL w;
} E[M * M * 2 + 8 * M];
int head[M * 2], tot;
bool vis[M * 2]; 
inline void add(int u, int v, int c, LL w) {E[tot] = (edge) {v, head[u], c, w}; head[u] = tot ++;E[tot] = (edge) {u, head[v], 0, -w}; head[v] = tot ++;
}
inline bool bfs(int s, int t) {memset(d, 0x3f, sizeof d); memset(incf, 0, sizeof incf);d[s] = 0, incf[s] = INF; queue< int > q; q.push(s); vis[s] = 1;while(!q.empty()) {int u = q.front(); q.pop(); vis[u] = 0;for(int i = head[u]; ~i; i = E[i].last) {int v = E[i].v;if(E[i].c && d[u] + E[i].w < d[v]) {d[v] = d[u] + E[i].w;incf[v] = min(incf[u], 1LL * E[i].c);pre[v] = i;if(!vis[v]) vis[v] = 1, q.push(v);}}}return incf[t] > 0;
}
inline LL EK(int s, int t) {int flow = 0; LL cost = 0;while(bfs(s, t)) {flow += incf[t]; cost += d[t] * incf[t];for(int u = t; u != s; u = E[pre[u] ^ 1].v) {E[pre[u]].c -= incf[t]; E[pre[u] ^ 1].c += incf[t];}}return cost;
}
int main() {scanf("%d%d", &n, &C);for(int i = 1; i <= n; i ++ ) {scanf("%lld%lld", &x[i], &y[i]);node[x[i] % (2 * C)].pb(i);}for(int x = 0; x < 2 * C; x ++ ) for(int y = x + 1; y < 2 * C; y += 2)  // 求 w(x, y) w[x][y] = solve(x, y);S = ++ idx, T = ++ idx;for(int i = 0; i < 2 * C; i ++ ) nd[i] = ++ idx;memset(head, -1, sizeof head);for(int i = 0; i < 2 * C; i += 2 ) add(S, nd[i], 1, 0);for(int i = 1; i < 2 * C; i += 2 ) add(nd[i], T, 1, 0);for(int x = 0; x < 2 * C; x += 2) for(int y = 1; y < 2 * C; y += 2 )  // 偶数往奇数连边 add(nd[x], nd[y], 1, w[min(x, y)][max(x, y)]);printf("%lld\n", EK(S, T));return 0;
}

相关文章:

  • (NAT64)IPv6网络用户访问IPv4网络服务器(动态映射方式)
  • 微内核与宏内核有什么区别(GAI)
  • Java -- 并发编程
  • 项目管理进阶:精读78页 IPD+CMMI+Scrum一体化研发管理解决方案【附全文阅读】
  • matlab雷达定位仿真
  • 约瑟夫问题
  • 企业级网络管理实战:Linux、云与容器的深度融合与优化
  • 关于无法下载Qt离线安装包的说明
  • 企业内训系统源码开发详解:直播+录播+考试的混合式学习平台搭建
  • Arduino 编码器
  • 2025-05-29 学习记录--Python-面向对象
  • 花哨桌面 V 3.0.0 (火影忍者版)
  • 每日刷题c++
  • 棋盘问题(放置棋子)
  • 【Phytium】飞腾FT2000/4 GPIO功能开发实例
  • Python实例题:Python实现Zip文件的暴力破解
  • 游戏盾在非游戏行业的应用实践与价值分析
  • leetcode:372. 超级次方(python3解法,数学相关算法题)
  • 【SQL】关键字
  • 在Spring Cloud中将Redis共用到Common模块
  • 怎样才能建设一歌网站/谷歌官方seo入门指南
  • 线上推广工作是做什么的/搜索引擎优化自然排名
  • 招标网站哪个好用/百度服务中心人工客服电话
  • 怎样做写真网站/qq推广链接
  • 运动鞋网站的建设风格/2023今日新闻头条
  • 电商网站推广怎么做/百度站长工具数据提交