23.10.9 CF div.2 总结

这次绝对算是我印象深刻的比赛了

A题思维题日常想不到,靠学长给的思路写了代码AC了。(蒻蒟日常)

题目:

Monocarp 有一个整数 n。

他想将他的数字表示为三个不同正整数 x、y 和 z 的总和。此外,Monocarp 希望数字 x、y 和 z 都不能被 33 整除。

您的任务是帮助 Monocarp 找到不同正整数 x、y 和 z 的任何有效三元组,或者报告这样的三元组不存在。

输入:

第一行包含一个整数 t(1≤t≤1e4) - 测试用例的数量。

每个测试用例的唯一行包含一个整数 n (1≤n≤1e9)。

输出:

对于每个测试用例,如果没有有效的三元组 x、y 和 z,则在第一行打印 NO。

否则,在第一行打印 YES。在第二行,打印不同正整数 x、y和 z 的任何有效三元组,使得 x+y+z=n且所有打印的数字都不能被 33 整除。如果有多个有效的三元组,您可以打印其中任何一个。

看到这题首先我自己的思路是这样的

从n/3、n%3出发,分情况讨论n % 3 == 1、n % 3 == 2等等情况,具体数值的话从n / 3 - 1、n / 3、n / 3 + 1出发,经加减得到答案,但是,这种思路的可行性肉眼可见的低,很麻烦而且极其容易漏算某些情况。

最后听到学长的解释:

可以先将x、y定为1、2这样只需考虑z % 3的情况。z % 3 != 0时直接输出n - 3就好了。

当z % 3 == 0 时,就换第二种特殊值,最小的1、4,因为(n - 3) % 3 = 0, 所以(n - 5) % 3 != 0;

直接输出1, 4, n - 5就好。

当然也要考虑数字不够大的情况,容易得到第一种情况时n一定大于6,第二种情况时n一定大于9。

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

void init()
{

}

void solve()
{
    int n; cin >> n;
    if(n <= 6)
    {
        cout << "NO" << '\n';
        return;
    }
    else if(n % 3)
    {
        cout << "YES" << '\n';
        cout << 1 << ' ' << 2 << ' ' << n - 3 << '\n';
    }
    else
    {
        if(n - 5 > 4) 
        {
            cout << "YES" << '\n';
            cout << 1 << ' ' << 4 << ' ' << n - 5 << '\n';
        }
        else cout << "NO" << '\n';
    }
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

B题的话看出条件还是很简单的

题目:

莫诺卡普试图下班回家。他当前位于二维平面的点O=(0,0));他的房子在点P=(Px,Py)

可惜现在已经是傍晚了,所以天色很暗。 Monocarp 害怕黑暗。他想沿着一条有什么东西照亮的路回家。

值得庆幸的是,有两个灯笼,位于点 A=(Ax,Ay) 和 B=(Bx,By)。您可以选择任何非负数 w 并将两个灯笼的功率设置为 w。如果灯笼的功率设置为 w,它将照亮以灯笼位置为中心、半径为 w 的圆(包括圆的边界)。

您必须为灯笼的功率选择最小非负值 w,以便从点 O 到点 P 存在一条被完全照亮的路径。您可能会认为灯笼不会干扰 Monocarp 的移动。

输入:

输入的第一行包含一个整数 t (1≤t≤1e4) — 测试用例的数量。

每个测试用例由三行组成:

第一行包含两个整数 Px 和 Py (−1e3≤Px,Py≤1e3) - Monocarp 房子的位置;

第二行包含两个整数 Ax 和 Ay (−1e3≤Ax,Ay≤1e3) - 第一个灯笼的位置;

第三行包含两个整数 Bx和 By  (−1e3≤Bx,By≤1e3) - 第二个灯笼的位置。

输入的附加约束:

在每个测试用例中,点O、P、A和B彼此不同。

输出:

对于每个测试用例,将答案打印在单独的一行上 - 一个等于 w 最小值的实数,以便从点 O到点 P 存在一条完全照亮的路径。

如果您的答案的绝对或相对误差不超过 1e−6,则将被视为正确 — 正式来说,如果您的答案为 a,而陪审团的答案为 b,则如果为 |a−b| / max(1,b)≤1e−6,您的答案将被接受。

因为是找w的值,左右边界不固定,但是可以写出固定的判断条件,于是就可以用二分来解决这个问题。

判断时分这几种情况:

1.原点和p点都在一个圆内

2.原点和p点在不同的圆内,此时需要满足两圆相交。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e9 + 5;

void init()
{

}
double px, py, ax, ay, bx, by;

bool check(double w)
{   
    //一个圆包含两个点
    if(sqrt((ax * ax) + (ay * ay)) <= w && sqrt((px - ax) * (px - ax) + (py - ay) * (py - ay)) <= w) return true;
    if(sqrt((bx * bx) + (by * by)) <= w && sqrt((px - bx) * (px - bx) + (py - by) * (py - by)) <= w) return true;

    //一个圆包含一个点
    if(sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by)) <= 2.0 * w)
    {
        int pt = 0;
        if(sqrt((ax * ax) + (ay * ay)) <= w || sqrt((bx * bx) + (by *by)) <= w) pt++;
        if(sqrt((px - ax) * (px - ax) + (py - ay) * (py - ay)) <= w || sqrt((px - bx) * (px - bx) + (py - by) * (py - by)) <= w) pt++;
        if(2 == pt) return true;
    }

    return false;
}

void solve()
{
     cin >> px >> py >> ax >> ay >> bx >> by;

    double l = 0.0, r = 40000.0;
    while(r - l > 1e-11)
    {
        double mid = (l + r) / 2.0;
        if(check(mid)) r = mid;
        else l = mid;
    }

    cout << fixed << setprecision(10)<< r << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _; cin >> _;
    init();
    while(_--) solve();
    return 0;
}

总结一下写这段代码遇到过的问题:

1.创建变量的时候没开全局,这导致了check函数里面写进去的参数一大堆,被批评了一顿(

2.判断条件写不全,写代码前还是要认真构思再去写。

3.中间小细节比如说括号的位置不对,感受到了空格的作用(

ending。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值