2021江苏省赛热身赛 C Magic Rabbit(数形结合)

2021江苏省赛热身赛 C Magic Rabbit(数形结合)

Magic Rabbit

非常好且巧妙地一道题。

大意:给出三种溶液 , 三种溶液分别含有不同浓度的 x ,y 两种物质。

溶液 x (mg/ml) y (mg/ml)
溶液1 x1 y1
溶液2 x2 y2
溶液3 x3 y3

给出 Q 组询问 , 每次给出一个新的溶液浓度(x4 , y4) , 问是否能用以上三种溶液混合出当前溶液。

思路:不妨设 溶液 1 , 2 , 3 分别取 a , b , c ml

显然可以得到式子

a x 1 + b x 2 + c x 3 a + b + c = x 4 \frac{ax_1+bx_2+cx_3}{a+b+c} = x_4 a+b+cax1+bx2+cx3=x4

a y 1 + b y 2 + c y 3 a + b + c = y 4 \frac{ay_1+by_2+cy_3}{a+b+c} = y_4 a+b+cay1+by2+cy3=y4

问题就变成了求这个方程组是否有解 , 显然是不好求的。

这时候我们转变思路 , 先求两种溶液的情况。

a x 1 + b x 2 a + b = x 4 \frac{ax_1+bx_2}{a+b} = x_4 a+bax1+bx2=x4

a y 1 + b y 2 a + b = y 4 \frac{ay_1+by_2}{a+b} = y_4 a+bay1+by2=y4

λ = a a + b \lambda = \frac{a}{a+b} λ=a+ba

λ x 1 + ( 1 − λ ) x 2 = x 4 \lambda x_1+(1-\lambda )x_2 = x_4 λx1+(1−λ)x2=x4

λ y 1 + ( 1 − λ ) y 2 = y 4 \lambda y_1+(1-\lambda )y_2 = y_4 λy1+(1−λ)y2=y4

转化成向量组的形式

x 2 y 2 \] + λ \[ x 1 − x 2 y 1 − y 2 \] = \[ x 4 y 4 \] ( 0 ≤ λ ≤ 1 ) \\begin{bmatrix} x_2\\\\y_2 \\end{bmatrix} +\\lambda \\begin{bmatrix} x_1-x_2\\\\y_1-y_2 \\end{bmatrix}=\\begin{bmatrix} x_4\\\\y_4 \\end{bmatrix}(0\\le \\lambda\\le 1) \[x2y2\]+λ\[x1−x2y1−y2\]=\[x4y4\](0≤λ≤1) ## 观察方程的左边 , 显然是一个直线的点向式的形式 , 这个式子表明 , 我们要求的解一定在(x1 , y1) (x2 , y2) 这两个点所形成的线段上(不考虑退化情况)。 ## 那么当加入第三个点之后 , 显然解一定在三点所形成三角形内部(包含端点) , 注意退化情况。 ```cpp #include using namespace std; #define fi first #define se second #define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); #define int long long const int N = 2e6 + 10; const int mod = 1e9 + 7; typedef pairPII; //-------------------------------------------------------------- const double eps = 1e-5; const double pi = acos(-1); inline double sqr(double x) {return x * x;} //平方 int sign(double x){ if(fabs(x) < eps) return 0; if(x > 0) return 1; return -1; }//符号 struct point{ double x , y; point(){} point(double a , double b) : x(a) , y(b){} friend point operator + (const point &a , const point &b){ return point(a.x + b.x , a.y + b.y); } friend point operator - (const point &a , const point &b){ return point(a.x - b.x , a.y - b.y); } friend bool operator == (const point &a , const point &b){ return !sign(a.x - b.x) && !sign(a.y - b.y); } friend point operator * (const point &a , const double &b){ return point(a.x * b , a.y * b); } friend point operator * (const double &a , const point &b){ return point(a * b.x , a * b.y); } friend point operator / (const point &a , const double &b){ return point(a.x / b , a.y / b); } //向量模长 double norm(){ return sqrt(sqr(x) + sqr(y)); } }; double det(const point &a , const point &b){ return a.x * b.y - a.y * b.x; }//叉积 判断两点共线 double dot(const point &a , const point &b){ return a.x * b.x + a.y * b.y; }//点积 double dist(const point &a , const point &b){ return (a - b).norm(); }//两点距离 point rotate_point(const point &a , const point &p , double A){ double tx = p.x - a.x , ty = p.y - a.y; return point(a.x + tx * cos(A) - ty * sin(A) , a.y + tx * sin(A) + ty * cos(A)); }// p 点 绕 a 点逆时针旋转 A 弧度 int toleft(const point &p , const point &a , const point &b) { return sign(det(b - a , p - a)); // 1 左 0 上 -1 右 }//只适用凸多边形 //判断点 p 是否在线段 st 上(包括端点) bool point_on_segment(point p , point s , point t){ return sign(det(p - s , t - s)) == 0 && sign(dot(p - s , p - t)) <= 0; } //判断两线段是否相交 ab cd bool segment_intersect(const point &a , const point &b , const point &c , const point &d){ //先判断 三点共线 或 四点共线 if(point_on_segment(a , c , d) || point_on_segment(b , c , d) || point_on_segment(c , a , b) || point_on_segment(d , a , b)) return 1; if(sign(toleft(a , c , d)) * sign(toleft(b , c , d)) < 0 && sign(toleft(c , a , b)) * sign(toleft(d , a , b)) < 0) return 1; return 0; } //-------------------------------------------------------------- point p[4] , now; double x , y; int n; signed main(){ IOS for(int i = 1 ; i <= 3 ; i ++){ cin >> x >> y; p[i] = point{x , y}; } cin >> n; int tag = -1; if(p[1] == p[2] && p[2] == p[3]) tag = 0; else if(point_on_segment(p[1] , p[2] , p[3])) tag = 1; else if(point_on_segment(p[2] , p[1] , p[3])) tag = 2; else if(point_on_segment(p[3] , p[1] , p[2])) tag = 3; else tag = 4; for(int i = 1 ; i <= n ; i ++){ cin >> x >> y; now = {x , y}; if(tag == 0){ if(now == p[1]) cout << "YES\n"; else cout << "NO\n"; } if(tag == 1){ if(point_on_segment(now , p[2] , p[3])) cout << "YES\n"; else cout << "NO\n"; } if(tag == 2){ if(point_on_segment(now , p[1] , p[3])) cout << "YES\n"; else cout << "NO\n"; } if(tag == 3){ if(point_on_segment(now , p[2] , p[1])) cout << "YES\n"; else cout << "NO\n"; } if(tag == 4){ bool f = 0; if(point_on_segment(now , p[2] , p[3]) || point_on_segment(now , p[1] , p[3]) || point_on_segment(now , p[2] , p[1])) f = 1; if(toleft(now , p[2] , p[3]) > 0 && toleft(now , p[3] , p[1]) > 0 && toleft(now , p[1] , p[2]) > 0) f = 1; if(toleft(now , p[2] , p[3]) < 0 && toleft(now , p[3] , p[1]) < 0 && toleft(now , p[1] , p[2]) < 0) f = 1; if(f) cout << "YES\n"; else cout << "NO\n"; } } return 0; } //freopen("文件名.in","r",stdin); //freopen("文件名.out","w",stdout); ```

相关推荐
QX_hao1 小时前
【Go】--map和struct数据类型
开发语言·后端·golang
你好,我叫C小白1 小时前
C语言 循环结构(1)
c语言·开发语言·算法·while·do...while
Evand J2 小时前
【MATLAB例程】基于USBL和DVL的线性回归误差补偿,对USBL和DVL导航数据进行相互补偿,提高定位精度,附代码下载链接
开发语言·matlab·线性回归·水下定位·usbl·dvl
朱嘉鼎3 小时前
状态机的介绍
c语言·单片机
爱喝白开水a3 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱
Neverfadeaway4 小时前
【C语言】深入理解函数指针数组应用(4)
c语言·开发语言·算法·回调函数·转移表·c语言实现计算器
武子康4 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
一碗绿豆汤4 小时前
c语言-流程控制语句
c语言
杰克尼4 小时前
JavaWeb_p165部门管理
java·开发语言·前端
一成码农4 小时前
JavaSE面向对象(下)
java·开发语言