H. Degenerate Matrix

H. Degenerate Matrix
time limit per test
 1 second
memory limit per test
 256 megabytes
input
 standard input
output
 standard output

The determinant of a matrix 2 × 2 is defined as follows:

A matrix is called degenerate if its determinant is equal to zero.

The norm ||A|| of a matrix A is defined as a maximum of absolute values of its elements.

You are given a matrix . Consider any degenerate matrix B such that norm ||A - B|| is minimum possible. Determine||A - B||.

Input

The first line contains two integers a and b (|a|, |b| ≤ 109), the elements of the first row of matrix A.

The second line contains two integers c and d (|c|, |d| ≤ 109) the elements of the second row of matrix A.

Output

Output a single real number, the minimum possible value of ||A - B||. Your answer is considered to be correct if its absolute or relative error does not exceed 10 - 9.

Sample test(s)
input
1 2
3 4
output
0.2000000000
input
1 0
0 1
output
0.5000000000
Note

In the first sample matrix B is 

In the second sample matrix B is 


觉得很好的一道题,题目链接:http://codeforces.com/contest/549/problem/H


题意:

给你一个2*2的矩阵A,让你构造一个矩阵B,矩阵B要满足两条对角线元素相乘结果相等,使得 ||A-B|| 值最小。||X||表示矩阵X中的4个元素中值最大的元素。


分析:

枚举增量(发现有很多二分都是枚举增量的),判断是否符合条件,然后缩小范围。

code:

[cpp]  view plain  copy
  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. typedef long double LD;  
  4. int a, b, c, d;  
  5. LD f1(int m1, int m2, LD x)  
  6. {  
  7.     return max(max((m1+x)*(m2+x),(m1+x)*(m2-x)),max((m1-x)*(m2+x),(m1-x)*(m2-x)));  
  8. }  
  9.   
  10. LD f2(int m1, int m2, LD x)  
  11. {  
  12.     return min(min((m1+x)*(m2+x),(m1+x)*(m2-x)),min((m1-x)*(m2+x),(m1-x)*(m2-x)));  
  13. }  
  14.   
  15. int Check(LD x)  
  16. {  
  17.     LD pr = f1(a,d,x); //(a..)*(d..) 与 (c..)*(b..) 比较,把它比作第一段和第二段,然后进行比较,是否会有等值情况  
  18.     LD pl = f2(a,d,x);  
  19.     LD qr = f1(c,b,x);  
  20.     LD ql = f2(c,b,x);   
  21.     if(pr < ql || qr < pl) return 0; //如果第一段与第二段不相交,则扩大两边使其可能相交  
  22.     else return 1; //如果已经相交,那么减小增量x使得两边缩小,更靠近结果  
  23. //这里我说得相交是将最大值与最小值看做两个点,连成的一条线段,最后两条线段的位置关系(yy的。。)  
  24.   //相交的部分代表值相等  
  25.   
  26. int main()  
  27. {  
  28.     scanf("%d%d%d%d", &a,&b,&c,&d);  
  29.     LD l=0, r=1e10;  
  30.     for(int i=0; i<200; i++)  
  31.     {  
  32.         LD mid = 0.5*(l+r);  
  33.         if(Check(mid)) r = mid;  
  34.         else l = mid; //增量x增大,那么结果的两边(最大值与最小值)会相应往两边扩(更大、更小)  
  35.     }  
  36.     printf("%.10f\n", (double)(0.5*(l+r)));  
  37.     return 0;  
  38. }  

做完上面这道题后,把本来一直不会做的下面这道题给秒了。。


序列变换

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 625    Accepted Submission(s): 305


Problem Description
给定序列 A={A1,A2,...,An} , 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为: Bi<Bi+1,1i<N )。

我们定义从序列A到序列B变换的代价为 cost(A,B)=max(|AiBi|)(1iN)

请求出满足条件的最小代价。

注意,每个元素在变换前后都是整数。
 

Input
第一行为测试的组数 T(1T10) .

对于每一组:
第一行为序列A的长度 N(1N105) ,第二行包含N个数, A1,A2,...,An .
序列A中的每个元素的值是正整数且不超过 106
 

Output
对于每一个测试样例,输出两行:

第一行输出:"Case #i:"。i代表第 i 组测试数据。

第二行输出一个正整数,代表满足条件的最小代价。
 

Sample Input
         
         
2 2 1 10 3 2 5 4
 

Sample Output
         
         
Case #1: 0 Case #2: 1

code:
[cpp]  view plain  copy
  1. #include<stdio.h>  
  2. int T, n, a[100010], b[100010];  
  3. bool Check(int x)  
  4. {  
  5.     for(int i=0; i<n; i++) b[i] = a[i];  
  6.     b[0] -= x;  
  7.     for(int i=1; i<n; i++)  
  8.     {  
  9.         int temp1 = b[i-1]-b[i]+1;  
  10.         int temp2 = b[i]-b[i-1]-1;  
  11.         if(b[i] <= b[i-1])  
  12.         {  
  13.             if(temp1 > x) return false;  
  14.             else b[i] = b[i-1]+1;  
  15.         }  
  16.         else  
  17.         {  
  18.             if(temp2 <= x) b[i] = b[i-1]+1;  
  19.             else b[i] -= x;  
  20.         }  
  21.     }  
  22.     return true;  
  23. }  
  24.   
  25. int main()  
  26. {  
  27.     scanf("%d", &T);  
  28.     for(int t=1; t<=T; t++)  
  29.     {  
  30.         scanf("%d", &n);  
  31.         for(int i=0; i<n; i++)  
  32.             scanf("%d", a+i);  
  33.         int l = 0, r = 1e6, mid;  
  34.         for(int i=0; i<20; i++)  
  35.         {  
  36.             mid = (l+r)/2;  
  37.             if(Check(mid)) r = mid;  
  38.             else l = mid;  
  39.         }  
  40.         printf("Case #%d:\n%d\n", t,r);  
  41.     }  
  42.     return 0;  
  43. }  


 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值