Educational Codeforces Round 88 (Rated for Div. 2) C. Mixing Water (思维,数学)

题目链接
题意:
给你一杯热水和一杯冷水,问你最少用几杯水,使得混合后的温度与给定的t温度最相近。
(这里至少要用一杯水,并且,交替使用,比如:第一杯只能用热水,第二杯只能用冷水,第三杯只能用热水依次下去。。。)

思路:

这里由于交替使用热水冷水,那么我们可以得出,要么,热水和冷水用的杯数一样多,要么热水比冷水多一杯
那么有俩种情况

1.如果冷水热水一样多,那么比例为 1:1 那么我们1杯热水1杯冷水和5杯热水5杯冷水也是1:1,同样的情况下,我们当然杯数越少越好。我们先判断杯数一样的,如果现在1:1的比例投入后,温度大于给定的温度,那么现在就是最小。因为热水总大于等于冷水的杯数,那么后面温度只会越来越高,相差越来越大,所以,第一种情况出来了。

2 如果热水总比冷水多一杯,那么我们可以列个方程
假设一共用a杯水,b杯热水,那么一定用了b-1杯冷水,热水温度为h,冷水温度为c,给定温度为t。

方程 h*(b/a) + c*((b-1) /a) == t
(由于是接近,所以不一定等于t,但是可以约等,那么现在的a解出来就可能是小数)

又由于b+(b-1) == a (热水的杯数加上冷水的杯数等于总杯数)那么可推出 b = (a+1)/2带入上述方程 化简得:

a = (c-h)/(h+c-2*t).
c,h,t题中都给出了的,所以这是一个一元一次方程

又由于a可能是小数,可能会有一定的误差,所以我在他的左右枚举了一下,以防万一,应该是可以用其他方法一步确认的,这个坑留给你们啦。。。嘻嘻

AC代码

#include 
inline int read(){char c = getchar();int x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
const int N = 1e6 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const unsigned long long mod = 998244353;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
double sum(ll i,ll h,ll c,ll t)
{
    return fabs( t - ( h*1.000*(i/2+1)/(i*1.00) + c*1.000*(i/2)/(i*1.000) ) );
    //求温度差的绝对值
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        ll h,c,t;
        cin >> h >> c >> t;
        if(h == t) cout << 1 << endl;//如果第一杯就相等了,就直接输出
        else if((h+c)/2 >= t) cout << 2 << endl;//如果已经大于等于了,现在就是最小
        else
        {
            ll num = (c-h)/(h+c-2*t),ans = 0;
            //num为推出的公式求的杯数,ans记录最小差值的杯数
            if(num <= 0) cout << 2 << endl;//如果为负数,那么这是不可能的,所以俩杯即可
            double Min = INF;
            for(ll i = num-10;i <= num+10;i++)//左右枚举一下
            {
                if(i <= 0 || i % 2 == 0) continue;//如果小于0,或者总杯数为偶数,即热水和冷水一样多的杯数
                double k = sum(i,h,c,t);//差值
                if(Min > k) Min = k,ans = i;//更新最小差值
            }
            cout << ans << endl;
        }
    }
}

你可能感兴趣的:(codeforces,数论,数学,思维)