首页 > 其他分享 >题解 NKOJ2929 【[THUSC2014] 函数求解】

题解 NKOJ2929 【[THUSC2014] 函数求解】

时间:2024-02-28 15:46:04浏览次数:28  
标签:pre end int 题解 flow edge NKOJ2929 THUSC2014 dis

代码:

#include <iostream>
#include <queue>
#include <cstdio>
#include <cmath>

using namespace std;

typedef struct {
	int nxt;
	int end;
	int dis;
	double cost;
} Edge;

const int N = 2e3, M = 400 + 7, K = 80800 + 7;
const double eps = 1e-7;
int cnt = 1;
int prime[N + 7], p[M], q[M], head[M], pre_dot[M], pre_edge[M];
double ln[N + 7], dis[M];
bool isnp[N + 7], mark[N + 7], vis[M];
Edge edge[K];
queue<int> que;

inline void init1(){
	int cnt = 0;
	for (register int i = 1; i <= N; i++){
		ln[i] = log(i);
	}
	isnp[0] = isnp[1] = true;
	for (register int i = 2; i <= N; i++){
		if (!isnp[i]) prime[++cnt] = i;
		for (register int j = 1; j <= cnt && i * prime[j] <= N; j++){
			isnp[i * prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}

inline void init2(int n){
	for (register int i = 0; i <= n; i++){
		dis[i] = 1e9;
	}
}

inline void add_edge(int start, int end, int dis, double cost){
	cnt++;
	edge[cnt].nxt = head[start];
	head[start] = cnt;
	edge[cnt].end = end;
	edge[cnt].dis = dis;
	edge[cnt].cost = cost;
}

inline void spfa(int start){
	dis[start] = 0.0;
	vis[start] = true;
	que.push(start);
	while (!que.empty()){
		int cur = que.front();
		que.pop();
		vis[cur] = false;
		for (register int i = head[cur]; i != 0; i = edge[i].nxt){
			if (edge[i].dis != 0){
				int x = edge[i].end;
				double y = dis[cur] + edge[i].cost;
				if (dis[x] - y > eps){
					dis[x] = y;
					pre_dot[x] = cur;
					pre_edge[x] = i;
					if (!vis[x]){
						vis[x] = true;
						que.push(x);
					}
				}
			}
		}
	}
}

inline double mincost(int n, int start, int end){
	double ans = 0.0;
	while (true){
		init2(n);
		spfa(start);
		if (dis[end] >= 0.0) break;
		int flow = 0x7fffffff;
		for (register int i = end; i != start; i = pre_dot[i]){
			flow = min(flow, edge[pre_edge[i]].dis);
		}
		for (register int i = end; i != start; i = pre_dot[i]){
			edge[pre_edge[i]].dis -= flow;
			edge[pre_edge[i] ^ 1].dis += flow;
		}
		ans += flow * dis[end];
	}
	return ans;
}

int main(){
	int m, d, end;
	double base = 0.0;
	cin >> m >> d;
	init1();
	for (register int i = 1; i <= d; i++){
		cin >> p[i] >> q[i];
		mark[p[i]] = true;
		base += ln[p[i]] * q[i];
	}
	for (register int i = 1, j = 1; i <= d; i++, j++){
		while (mark[prime[j]]) j++;
		p[i + d] = prime[j];
	}
	d *= 2;
	end = d * 2 + 1;
	for (register int i = 1; i <= d; i++){
		int i_ = i + d;
		add_edge(0, i, 1, 0.0);
		add_edge(i, 0, 0, 0.0);
		for (register int j = 1; j <= d; j++){
			double delta = (ln[p[i]] - ln[p[j]]) * (q[j] - q[i]);
			if (delta < 0.0){
				int j_ = j + d;
				add_edge(i, j_, 1, delta);
				add_edge(j_, i, 0, -delta);
			}
		}
		add_edge(i_, end, 1, 0.0);
		add_edge(end, i_, 0, 0.0);
	}
	printf("%.4lf", base + mincost(end, 0, end) / 2.0);
	return 0;
}

标签:pre,end,int,题解,flow,edge,NKOJ2929,THUSC2014,dis
From: https://www.cnblogs.com/Leasier/p/18040640

相关文章

  • ABC294 EFG 题解
    E-2xNGrid题意给你一个\(2\timesL\)的网格,但是\(L\)很大,所以用以下形式压缩:将同一个颜色的连续段视为一个整体,那么每一行就可以用若干个二元组\((a_i,b_i)\)表示,其中\(a_i\)为颜色,\(b_i\)为连续段的长度。保证长度\(\le10^5\)。输入以上述形式压缩,现在让你求出......
  • P1110 [ZJOI2007] 报表统计 题解
    考察点:STL的熟练运用。记:\(l_i\)表示序列中不超过\(a_i\)的最大数,\(r_i\)表示序列中超过\(a_i\)的最小数。开一个vectorinsert[N]存储\(a_i\)后面插入的所有数字。首先,我们使用一个multisets1来存储相邻元素的差的绝对值,然后再开一个multisets2来存储当前出......
  • CodeChef Chef and Churus 题解
    对给出的\(n\)个区间分块,设块长为\(B\)。每个块内计算每个位置的贡献(被覆盖次数)。具体地,记\(f_{i,j}\)表示第\(i\)个块第\(j\)个数被覆盖了多少次,这个可以用差分轻松维护。预处理复杂度\(O(\frac{n^2}{B})\)。现在考虑修改。记\(ans_i\)表示块\(i\)的贡献,那么对于......
  • ABC303 G 题解
    区间DP。设\(f_{l,r}\)表示只考虑\([l,r]\),先手得分减后手得分的最大值(并不关心谁是先手谁是后手),区间长度\(len=r-l+1\)。然后对三种情况分别讨论:使用操作一,此时取掉左/右端点的部分先手后手互换,对答案的贡献为\(\max(a_l-f_{l+1,r},a_r-f_{l,r-1})\)。使用操作二,继......
  • P1668 题解
    两种做法。一、最短路题目要求区间数量最小。如果能建出图来,就可以转换为最短路问题。具体地,我们从\(l-1\tor\)连一条长度为\(1\)的边,意味着要多经过\((l-1,r]\)这一个区间。这是左开右闭的形式。现在还有一个问题:通过这种边我们只能到达区间的右端点,如果想向左到达区......
  • P1266 速度限制 题解
    考虑分层图。把图按速度分成\(V\)层,\(f_{i,j}\)表示点\(i\)在第\(j\)层(速度为\(j\))的编号。注意:这里的速度为\(j\)是指到达\(i\)那一条边的速度(\(i\)为终点)。考虑一种naive的建边方式:首先,记当前点为\(u\),速度为\(i\);\(u\)的出边速度为\(j\),长度为\(l\),终点......
  • ABC302 Ex 题解
    首先我们考虑\(v\)固定怎么做。实际上就是ARC111B。考虑建图,对每个\((a_i,b_i)\)建一条无向边,那么问题就变成了:对于每条边都要选择它以及其连接的一个点,最大化选出的点数。很明显可以对每个连通块分开考虑。记当前连通块的点数为\(V\),边数为\(E\)。那么有结论:该连通块对......
  • ABC301 Ex 题解
    题意:你有一张无向连通图,定义\(d(s,t)\)表示从\(s\)到\(t\)所有路径中最大边权的最小值。现在给你三个数\(A_i,S_i,T_i\),让你求出当\(A_i\)这条边的边权\(+1\)时,\(d(S_i,T_i)\)会增加多少。首先考虑一下\(A_j+1\)什么时候会对\(d(S_j,T_j)\)有影响。\(A_j>d(S_......
  • 第五届图灵杯中级组题解
    网址赛时得分\(25+50+5+1=81\),rk67,逊死了。赛后发现T1爆搜+剪枝有\(50\)分,我【】【】。总结:还是菜。A.等差数列首先特判\(n\le4\)的情况。此时答案必然为Yes,只需要两两分组即可。由于第一个数必然在其中一个等差数列内,不妨强制令其在第一个等差数列内。考虑......
  • CF351D - Jeff and Removing Periods 题解
    首先做一点显然的转化:在进行第一次操作之后,可以将相同的数排在一起,这样一次就能删掉一种数。如果一开始就能删光一种数的话,那么次数就是区间颜色数,否则就是区间颜色数\(+1\)。所以现在原问题变成了两个问题:求区间内不同颜色数,判断区间内是否有某种颜色满足其出现位置构成等差数......