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); ```

相关推荐
YuforiaCode2 分钟前
第十二届蓝桥杯 2021 C/C++组 直线
c语言·c++·蓝桥杯
我真的不会C6 分钟前
QT窗口相关控件及其属性
开发语言·qt
CodeCraft Studio6 分钟前
Excel处理控件Aspose.Cells教程:使用 Python 在 Excel 中进行数据验
开发语言·python·excel
火柴盒zhang12 分钟前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet
景天科技苑19 分钟前
【Rust】Rust中的枚举与模式匹配,原理解析与应用实战
开发语言·后端·rust·match·enum·枚举与模式匹配·rust枚举与模式匹配
阿让啊25 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
椰羊~王小美30 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
拾忆-eleven40 分钟前
C语言实战:用Pygame打造高难度水果消消乐游戏
c语言·python·pygame
孞㐑¥1 小时前
C++11介绍
开发语言·c++·经验分享·笔记
旦莫1 小时前
Python 教程:我们可以给 Python 文件起中文名吗?
开发语言·python