zoukankan      html  css  js  c++  java
  • 洛谷 AT249 紅茶(Tea)

    洛谷 AT249 紅茶(Tea)

    题目链接:洛谷 AT249 紅茶(Tea)

    算法标签: 模拟二分

    题目

    题目描述

    一天,(kagamiz) 一边喝红茶,一边尝试解答如下的问题:

    当由两个正整数所组成的正整数组以如下方式排列时, ((m,n))是这个数列里的第几组?

    ((1,1),(2,1),(1,2),(3,1),(2,2),(1,3),(4,1),(3,2),(2,3),(1,4),(5,1),…)

    这个问题对他来说太简单了,所以他更深入地考虑了以下这个问题:

    当上述数列中的 (i) 个组为((a_i,b_i)),第 (j) 个组为((a_j,b_j))时, ((a_i+a_j,b_i+b_j))是这个数列里的第几组?

    你的任务就是帮助他解答这个问题。

    输入格式

    输入仅一行,为两个正整数 (i,j)

    输出格式

    输出为一个正整数,表示当上述数列中的第(i)个组为((a_i,b_i)), 第(j)个组为((a_j,b_j))时, ((a_i+a_j,b_i+b_j))是这个数列里的第几组。

    输入输出样例

    输入 #1

    1 1
    

    输出 #1

    5
    

    输入 #2

    3 2
    

    输出 #2

    13
    

    输入 #3

    114 514
    

    输出 #3

    1155
    

    说明/提示

    数据范围:

    • (i≥1,1≤j≤10^8),且(i,j)均为正整数。
    • (i,j) 可能相等。

    题解:

    首先这道题我们要看所给出的数对:

    ((1,1),(2,1),(1,2),(3,1),(2,2),(1,3),(4,1),(3,2),(2,3),(1,4),(5,1),…)

    我们可以发现,和为(n)的数对共有(n - 1)对,所以可以根据这个规律来统计所询问为第几组。

    之后继续观察,在每一个合为(n)的数对组中,第一位是从 (n - 1)(1) 递减的,而第二位则正好相反,从 (1)(n - 1)递增,这个可以统计为第几行(将所有和相等的数对看做一行)的第几个。

    同样由于本题的数据范围 (1 ≤ j ≤ 10^8) ,显然我们暴力进行查询和求和是很受限制的(没有测过),所以我们选择使用等差数列求和二分答案的方式进行求解,具体代码实现如下:

    long long getsum(ll q) // 等差数列求和
    {
        return 1ll * ((1 + q) * q) / 2;
    }
    void find(long long q) // 二分查找答案
    {
        ll l = 1, r = N + 1, mid;
        while(l < r)
        {
            mid = (l + r) >> 1;
            if (getsum(mid) >= q)
                r = mid;
            else 
                l = mid + 1;
        }
        yy = q - getsum(l - 1);
        xx = l - yy + 1;
    }
    

    AC代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    const int N = 1e8 + 10;
    typedef long long ll;
    int xx, yy;
    long long getsum(ll q)
    {
        return 1ll * ((1 + q) * q) / 2;
    }
    void find(long long q)
    {
        ll l = 1, r = N + 1, mid;
        while(l < r)
        {
            mid = (l + r) >> 1;
            if (getsum(mid) >= q)
                r = mid;
            else 
                l = mid + 1;
        }
        yy = q - getsum(l - 1);
        xx = l - yy + 1;
    }
    int main()
    {
        ll x, y;
        scanf("%lld%lld", &x, &y);
        find(x);
        ll ax = xx, ay = yy;
        find(y);
        ll bx = xx, by = yy;
        ll qx = ax + bx, qy = ay + by;
        ll pos = qx + qy - 1;
        pos = getsum(pos - 1) + qy;
        printf("%lld
    ", pos);
        return 0;
    }
    
  • 相关阅读:
    获取打印页号列表
    数据库设计技巧系列(三)——选择键和索引
    SQL Server2000孤立用户解决方案
    在WinForm程序中嵌入ASP.NET[转]
    再谈如何遍历Asp.net窗体下所有的控件
    数据库设计技巧系列(二)——设计表和字段
    今天下午真郁闷……
    如何实现在Asp.net下XP风格的下拉菜单
    利用SQL语句得到客户端的IP地址
    国庆节快乐……
  • 原文地址:https://www.cnblogs.com/littleseven777/p/11845655.html
Copyright © 2011-2022 走看看