当前位置: 首页 > news >正文

成都专业的网站建设制作公司哪家好/百度关键词首页排名

成都专业的网站建设制作公司哪家好,百度关键词首页排名,云南网站建设费用,网页设计个人简历模板题目如下 四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和。 如果把0包括进去,就正好可以表示为4个数的平方和。 比如: 5 0^ 2 0^ 2 1^ 2 2^2 7 1^ 2 1^ 2 1^ 2 2^2 (^符号…

题目如下

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

每个正整数都可以表示为至多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 (N<5000000)

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

例如,输入:

5

则程序应该输出:

0 0 1 2

再例如,输入:

12

则程序应该输出:

0 2 2 2

再例如,输入:

773535

则程序应该输出:

1 1 267 838

以下程序实现了这一功能,请你补全空白处内容:

#include <bits/stdc++.h>
using namespace std;typedef long long LL;
const int MAXN = 2500010;
struct Node
{int s, c, d;bool operator<(const Node &t) const{if (s != t.s)return s < t.s;if (c != t.c)return c < t.c;return d < t.d;}
} sum[MAXN];
int n, m;
int main()
{cin >> n;for (int c = 0; c * c <= n; c++)for (int d = c; c * c + d * d <= n; d++)sum[m++] = {c * c + d * d, c, d};sort(sum, sum + m);for (int a = 0; a * a <= n; a++){for (int b = 0; a * a + b * b <= n; b++){int t = n - a * a - b * b;int l = 0, r = m - 1;while (l < r){__________________;if (sum[mid].s >= t)r = mid;elsel = mid + 1;}if (sum[l].s == t){printf("%d %d %d %d", a, b, sum[l].c, sum[l].d);return 0;}}}return 0;
}

提示:

二分法降低时间复杂度
用打表空间换时间

感慨:这道题难度还是有些大的,博主也是看了好一会才想到才搞懂题目中提供的部分代码是什么意思,这里提供两种解题思路供大家思考,每种解题思路都会附上详细解释,接下来走起:

解题思路一 

#include <bits/stdc++.h>
using namespace std;typedef long long LL;
const int MAXN = 2500010;
struct Node
{int s, c, d;bool operator<(const Node &t) const{if (s != t.s)return s < t.s;if (c != t.c)return c < t.c;return d < t.d;}
} sum[MAXN];
int n, m;
int main()
{cin >> n;for (int c = 0; c * c <= n; c++)for (int d = c; c * c + d * d <= n; d++)sum[m++] = {c * c + d * d, c, d};sort(sum, sum + m);for (int a = 0; a * a <= n; a++){for (int b = 0; a * a + b * b <= n; b++){int t = n - a * a - b * b;int l = 0, r = m - 1;while (l < r){int mid = l + r >> 1;if (sum[mid].s >= t)r = mid;elsel = mid + 1;}if (sum[l].s == t){printf("%d %d %d %d", a, b, sum[l].c, sum[l].d);return 0;}}}return 0;
}

1.struct Node

这是一个结构体内嵌比较函数。

struct node
{int l,r;bool operator <(const node &a)const{return r < a.r;}
}a[maxn];

这种是最经典的。
r相当于当前正在比较的值,这个函数就是r从小到大排。
存储用优先队列时则会相反,同是上面这个函数会按r从大到小排。

优先队列如下:

struct node
{int l,r;bool operator <(const node &a)const{return r>a.r;}
};
priority_queue<node> q;

但是本题中我们明显不需要这么做,只做扩展用,大家看看就好,了解一下。

本题中代码如下: 

struct Node
{int s, c, d;bool operator<(const Node &t) const{if (s != t.s)return s < t.s;if (c != t.c)return c < t.c;return d < t.d;}
} sum[MAXN];

其实这里还什么都没做,熟悉c++的同学应该知道这是个结构体,用sum数组的形式来存储Node结构体内的一些参数。

2.枚举c,d的for循环

    cin >> n;for (int c = 0; c * c <= n; c++)for (int d = c; c * c + d * d <= n; d++)sum[m++] = {c * c + d * d, c, d};sort(sum, sum + m);

 从for循环中,我们看到首先对c,d进行了取值,取出所有满足条件的值,这个应该不难理解,接着看sum:

sum[m++] = {c * c + d * d, c, d};

其实我觉得这里有点问题,m应该初始值为0才对,博主学c++时间不久,不给初始值直接++是否存在问题,还望小伙伴们指出来,运行发现m初始值确为0,在其他语言中,根据博主多年经验,不给初始值是不行的。

这里备注下:如果将m = 0,那么第一项势必是1,而不是0,所以c++里面才有了这种操作?

但是也可以通过m = 0,在sum[m]之后,进行m++。有懂的小伙伴评论区解答下,感谢!

这段代码是将c的平方和d的平方相加作为s,然后将s,c,d存入了结构体Node中,继而存入初始值为1的sum数组中,这样就得到了所有满足条件的c和d ,还有其平方和的值s。

结构体内嵌比较函数的使用就是直接sort就可以,sort(a,a+n);首先c一定是小于等于d的,这一点,在for循环中很容易看出来,因为d = c,d++。这里sort针对s的大小进行排序从小到大。

3.接下来要对a和b进行枚举了

    for (int a = 0; a * a <= n; a++){for (int b = 0; a * a + b * b <= n; b++){int t = n - a * a - b * b;int l = 0, r = m - 1;while (l < r){int mid = l + r >> 1;if (sum[mid].s >= t)r = mid;elsel = mid + 1;}if (sum[l].s == t){printf("%d %d %d %d", a, b, sum[l].c, sum[l].d);return 0;}}}

两个for循环不难看懂,是a和b的平方是必须要小于n的,这点没毛病,这里为了节省加快运算效率快速找到合适的a和b,采用了二分法,l=0,r=m-1。

有意思的是下面这段代码:

int mid = l + r >> 1;

博主在其他语言里真的没这么用过,只是知道是右移一位的意思,了解下,好神奇:

这是比特操作,如
12的二进制表示是00001100,12>>1将00001100右移一位,变为00000110,即6.
又如
15的二进制表示是00001111,15>>1将00001111右移一位,变为00000111,即7.
另外<<就是左移,相当于乘以2. 

这里博主用的编辑器提示>>运算符优先级低于+,所以需要将r>>1用括号括起来,同学们注意。

接下来看比较的部分:

int t = n - a * a - b * b;
int l = 0, r = m - 1;
while (l < r)
{int mid = l + r >> 1;if (sum[mid].s >= t)r = mid;elsel = mid + 1;
}

 t是符合条件的a和b平方后被n减后留给c和d平方和的最大数。

l是初始位,r为最大为,mid为中间为,每一次if之后,r和l重新给值,范围缩小一半,二分法,不详细说了。

直到sum[l].s == t,这里解释下,sum[mid]对应的s必须是小于等于t才能继续循环下去,不过这里用了>=是不是存在一定的问题呢,如果等于的话,sum[l].s == t,这时的mid不是刚好满足条件吗?但还需要再循环一次让sum[mid].s > t,之后执行l=mid+1才能让sum[l].s == t,多些一个判断条件来判断mid我觉得更好。

满足条件后:

printf("%d %d %d %d", a, b, sum[l].c, sum[l].d);
return 0;

输出,并直接返回,此时的a,b,c,d即是符合题目要求的,按从小到大排序的合理数字。

解题思路二
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_map>#define x first
#define y secondusing namespace std;typedef pair<int, int> PII;int main()
{int n;cin >> n;unordered_map<int, PII> ans;for(int c = 0; c * c <= n; c ++ )//枚举C和Dfor(int d = c; d * d + c * c <= n; d ++ ){int t = c * c + d * d; //存下来这两个数的平方和if(ans.count(t) == 0)   ans[t] = {c, d};}for(int a = 0; a * a <= n; a ++ )for(int b = a; b * b + a * a <= n; b ++ ){int t = n - a * a - b * b;//看A和B的平方和还和目标差多少,看看之前存的有没有这个数if(ans.count(t) != 0){printf("%d %d %d %d\n", a, b, ans[t].x, ans[t].y);return 0;}}return 0;
}

这个解题思路理解起来就容易的多了:

int t = c * c + d * d; //存下来这两个数的平方和
if(ans.count(t) == 0)   ans[t] = {c, d};

它是采用unordered_map的方式,这是用于存储键值和映射值组合成的元素的关联容器,以c和d的平方和sum为key, 存储一个c和d的关联容器,和第一种结构中的结构体很相似。

接着是和的判断组合:

int t = n - a * a - b * b;
//看A和B的平方和还和目标差多少,看看之前存的有没有这个数
if(ans.count(t) != 0)
{printf("%d %d %d %d\n", a, b, ans[t].x, ans[t].y);return 0;
}

这里反其道而行之,不通过二分法下标去寻找值,而是根据t,也就是留给c和d平方和的最大数作为key去ans中寻找是否存在这样的sum值,这个sum值在上面介绍了,是c和d的平方和,被作为key存入了map中,只要ans.count(t) != 0,就说明存在这样的一个c和d。

总结

个人认为,第二种解题思路让人更容易理解,也更加简单直观,从效率上来说,第二种明显是要高效一点的,因为通过准确的键值去寻找符合的c和d。想出这种解题思路的人真是厉害,佩服。

看题1小时,写博客三个小时,写完之后思路更加清晰了,不知道同学们搞明白没?欢迎评论区留言讨论。 

http://www.jmfq.cn/news/4825225.html

相关文章:

  • 营商环境建设局网站/seo网站推广全程实例
  • 手机网站 触屏/百度推广二级代理商
  • 注册网站能赚钱吗/域名注册新网
  • 网站淘宝推广怎么做/如何做营销策划方案
  • 门户网站建设好处/今日头条新闻视频
  • 长沙微营销/石家庄seo
  • 网站制作销售术语/2022最火营销方案
  • 湖南省金力电力建设有限公司 网站/seo排名怎么看
  • 在线旅游攻略网站建设方案/软文推广平台排名
  • 电脑上怎么下载字体到wordpress/商丘 峰少 seo博客
  • 做幼儿园网站/广州网页seo排名
  • 专业做皮草的网站/网站自助搭建
  • 做cpa能用什么网站/宁波超值关键词优化
  • 网站正建设中/2023年6月份又封城了
  • 深圳最新新闻事件/网店产品seo如何优化
  • 太原建站模板搭建/百度客户管理系统登录
  • 做经营性的网站需要注册什么/网站seo排名优化
  • 网站的建设需要多少钱/关键词推广效果
  • 网站开发赚钱/seo营销推广平台
  • 哈尔滨做网站/营销方式
  • 网站建设技巧饣金手指排名27/seo推广代运营
  • 网站开发demo是什么/百度权重是什么意思
  • 网站建设的好不好/google首页
  • 网站标题会影响吗/优化服务是什么意思
  • 新疆建设厅造价网站/链接推广
  • 网站设计流程软件/网络推广方式有哪些
  • 上海自适应网站建设/搜索引擎整合营销
  • 礼信堂 网站开发/什么关键词可以搜到那种
  • 成都哪里做网站好/百度推广登录入口电脑
  • 如何建立一个大型的网站/网站推广seo设置