首页 > 其他分享 >蓝桥杯-四平方和

蓝桥杯-四平方和

时间:2024-05-06 20:12:39浏览次数:13  
标签:Node return int sum mid 平方和 蓝桥

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多 4 个正整数的平方和。

如果把 0 包括进去,就正好可以表示为 4 个数的平方和。

比如:

5= 0^2 + 0^2 + 1^2 + 2^2

7= 1^2 + 1^2 + 1^2 + 2^2

对于一个给定的正整数,可能存在多种平方和的表示法。

要求你对 4 个数排序:

0≤a≤b≤c≤d

并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法。

输入格式

输入一个正整数 N。

输出格式

输出4个非负整数,按从小到大排序,中间用空格分开。

数据范围

0<N<5∗1e6

输入样例:

5

输出样例:

0 0 1 2

题解:

暴力three重循环判断会超时~

  • 枚举 c 和 d 的所有可能, 并把 c, d, c * c + d * d 都存到数组中
  • 对数组排序。 (从大到小, 从小到达都行, 但对应的二分不一样)
  • 枚举 a 和 b 的所有可能, 用二分找 当前 a b 下, 对应的 c d, 判断是否满足 n = a * a + b * b + c * c + d * d, 满足的话输出并退出ok了
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
struct Node {
    int c, d, sum;
};
Node v[N];
bool cmp(Node a, Node b)
{
    if (a.sum != b.sum) return a.sum < b.sum;
    if (a.c != b.c) return a.c < b.c;
    return a.d < b.d;
}

int main()
{
    int n, m = 0; cin >> n;
    for (int i = 0; i * i <= n; i ++)
        for (int j = i; i * i + j * j <= n; j ++)
            v[m ++] = {i, j, i * i + j * j};
    sort(v, v + m, cmp);  // 从小到大排序
    
    for (int i = 0; i * i <= n; i ++)
        for (int j = 0; j * j + i * i <= n; j ++)  // a b 要从 0 开始枚举, 题中要求a≤b≤c≤d
        {
            int l = 0, r = m - 1;
            int t = n - i * i - j * j;
            while (l < r)
            {
                int mid = l + r >> 1;
                if (v[mid].sum >= t) r = mid;  // 二分, 相同的v[mid].sum, 查找的是第一个满足的, 由于我们是 升序, 刚好满足 c <= d
                else l = mid + 1;
            }
            if (v[l].sum == t)
            {
                cout << i << ' ' << j << ' ' << v[l].c << ' ' << v[l].d << endl;
                return 0;
            }
        }
    return 0;
}

觉得写的不错的话, 点个赞吧~




下面不是题解, 是笔者为了让自己更好理解二分写的笔记

  • 对比上面的代码可以发现 代码中有 "<--------" 注释的是发生改变的
  • 其中 if (v[mid].sum <= t), 二分条件发生变化, 导致了 这个二分在 v[mid].sum 相同的情况下, 找到的是 最后一个 符合条件的 下标
  • 上面的代码在 v[mid].sum 相同的情况下, 找到的是 第一个 符合条件的 下标
  • so 在下面代码排序中我们是让 c 和 d 按照倒序的方法排的顺序
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
struct Node {
    int c, d, sum;
};
Node v[N];
bool cmp(Node a, Node b)
{
    if (a.sum != b.sum) return a.sum < b.sum;
    if (a.c != b.c) return a.c > b.c;  // <------
    return a.d > b.d;       // <-------
}

int main()
{
    int n, m = 0; cin >> n;
    for (int i = 0; i * i <= n; i ++)
        for (int j = i; i * i + j * j <= n; j ++)
            v[m ++] = {i, j, i * i + j * j};
    sort(v, v + m, cmp);
    
    for (int i = 0; i * i <= n; i ++)
        for (int j = 0; j * j + i * i <= n; j ++)
        {
            int l = 0, r = m - 1;
            int t = n - i * i - j * j;
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (v[mid].sum <= t) l = mid;   // <-------
                else r = mid - 1;   // <-------
            }
            if (v[l].sum == t)
            {
                cout << i << ' ' << j << ' ' << v[l].c << ' ' << v[l].d << endl;
                return 0;
            }
        }
    return 0;
}

口诀
if 后面是 r 的话 找到的是 l 的, 即 是 第一个 满足条件的
if 后面是 l 的话 找到的是 r 的, 即 是 最后一个 满足条件的

标签:Node,return,int,sum,mid,平方和,蓝桥
From: https://www.cnblogs.com/xxctx/p/18175777

相关文章

  • 蓝桥杯-k倍区间
    给定一个长度为N的数列,A1,A2,…AN,如果其中一段连续的子序列Ai,Ai+1,…Aj之和是K的倍数,我们就称这个区间[i,j]是K倍区间。你能求出数列中总共有多少个K倍区间吗?输入格式第一行包含两个整数N和K。以下N行每行包含一个整数Ai。输出格式输出一个整数,代表K倍......
  • 蓝桥杯-分巧克力
    儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是Hi×Wi的方格组成的长方形。为了公平起见,小明需要从这N块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:形状是正方形,边长是整数大小相同......
  • 2024第十五届蓝桥杯网络安全赛项部分题目 WriteUp
    2024第十五届蓝桥杯网络安全赛项部分题目WriteUp爬虫协议根据提示,访问/robots.txt,得到敏感路径/38063b612387b10e22f4bd0d71a46a4e/,访问其中的/9de33df789dc91e984a091e6dce2dfb1得到flag。flag{494547b4-f13f-47de-b1a5-a99f20495cd7}packet使用过滤器tcpcontains"fla......
  • 第十五届蓝桥杯 网络安全赛道 ezjava
    1.前言前一秒还在robots.txt找flag,下一秒就java内存马了,还不出网,这很......
  • 蓝桥杯-数的划分(DFS)
    0.题目问题描述将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。例如:n=7,k=3,下面三种分法被认为是相同的。1,1,5;1,5,1;5,1,1;问有多少种不同的分法。输入格式n,k输出格式一个整数,即不同的分法样例输入73样例输出4数据......
  • 2024蓝桥杯省赛C/C++程序设计A组题目简析
    2024蓝桥杯省赛C/C++程序设计A组题目简析A题意:计算一段区间内日期的中文表达的总笔画数>50的天数按照题意枚举即可。注意个位数字前面需要加一个“零”,也就是多13笔。B题意:\(5\times5\)的棋盘下五子棋,最终下满棋盘并和棋的情况数dfs或者遍历二进制去枚举棋子位置的情况均可......
  • 【2024蓝桥B组】好数
    好数题目 题目分析1.蓝桥杯不怕麻烦的,一般可以选择用longlongint替换int,防止数据过大2.这道题不怕麻烦的话,可以直接暴力解,用多个if语句进行判断即可3.想要美观点的,就进行数位判断4.这道题就一个关键点:奇数位对奇数,偶数位对偶数代码1#include<iostream>usingname......
  • 第十五届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组
    Preface答辩圈钱杯,去年省赛的题好歹还有些有意思的题(指杜教筛),今年变成煞笔题开会了是吧两个小时多一点就全写完了,然后开始给后面三题写对拍(结果发现其实都没写挂纯在浪费时间)考完感觉AK有望,结果后面发现最后一题漏看条件了,苦露西而且中间EF两题全偷懒开__int128了,反正用下发的......
  • 【2024蓝桥B组】小球反弹
    小球反弹题目题目分析一个比较绕脑的数学问题。。。首先:小球能过从左上角出发,然后回到左上角,那么其x方向的路径长度则为2k1x,y方向的路径长度则为2k2y。其次,我们得知其x与y的速度比值为15:17,由公式:时间*速度=路程可得:t*dx=2k1x,t*dy=2k2y然后,通过简单的数学变换,我们可以得出:k......
  • 第十五届蓝桥杯C++B组省赛总结
    A握手问题简单模拟,答案为:12045ptsB小球反弹数学,最重要的一点,不考虑反弹,一直让小球走,直到达到一个顶点,它就会反弹回去。所以问题就变成了扩展这些方块,直到满足小球的角度,让小球能达到另一个顶点。\(233333\times15a=343720\times17b\)解出来a和b就知道我们要延......