百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

for循环的使用和优化解整数不定方程

toyiye 2024-04-07 14:12 16 浏览 0 评论

定性分析

这个方程的整数解怎么得到?

方程:



函数f1、f2和f3:



f1和f2的导数,也就是曲线f的斜率, 理论上f2的斜率是比f1越来越陡峭,f1和f2只有有限的几个交点。



方程的整数解是曲线f1和f2的交点。 由于f1画图不方便, 可以从f2和f3的形态推知f1和f2只有有限的交点。因为f3只是f1的平移。 f2和f3的图像示意如下, 明显只有有限个交点。

ps: x是对称的,所以如果有整数解x则-x也是其解。下面讨论都是基于x为正整数。


大力出奇迹

思路

不管三七二十一,x和y都从0开始,按照自然数递增的方式去试探。

两层循环,外层是x, 内层是y。然后尝试计算f1和f2, 如果f1 == f2 就打印结果,终止循环。

不过这里可做一点点局部优化,就是x^2+615=2^y >=615 可以推出y>9。外层循环x 从0开始,内存循环可以从10开始。

代码

equation.cpp

#include <iostream>
#include <cmath>
using namespace std;

int main(int argc, char* argv[])
{
    if (argc < 3) return -1;
    long n = atol(argv[1]);
    long m = atol(argv[2]);
    bool flag = false; //找到解的标志,找到为true未找到为false
    for (long x = 0; x < n && !flag; x++) //x没到循环上限值且未找到解的就继续
    {
       for (long y = 10 ; y < m; y++)
       {
          long long f1 = 615 + pow(x, 2);
          long long f2 = pow(2, y);
          if (f1 == f2) //找到,打印解
          {
              flag = true;
              cout << "(x, y)" << ":" << "(" << x << "," << y << ")" << endl;
              cout << "(x, y)" << ":" << "(" << -x << "," << y << ")" << endl;//共轭解
              break;
          }
       }
    }
    return 0;
}

复制代码

代码解读

n 和 m是通过命令输入,来控制x和y的上限的。

flag 为找到解的标志。

外层循环的终止条件是表示式 x < n && !flag 的值为false。

这个解法非常自然,基本属于大力出奇迹的范围。

执行结果



局部优化

思路

  • 减少外层循环次数。
  • 参考视频,推断x的形式为6k+1或6k-1 ,k为整数

代码

#include <iostream>
#include <cmath>
using namespace std;

int main(int argc, char* argv[])
{
    if (argc < 3) return -1;
    long n = atol(argv[1]);
    long m = atol(argv[2]);
    bool flag = false;
    for (long k = 1; k < n && !flag; k++)
    {
       for (long y = 10 ; y < m; y++)
       {
          long long f1 = 615 + pow(6*k - 1, 2);
          long long f2 = pow(2, y);
          if (f1 == f2)
          {
              flag = true;
              cout << "(x, y)" << ":" << "(" << 6*k - 1 << "," << y << ")" << endl;
              cout << "(x, y)" << ":" << "(" << -(6*k -1) << "," << y << ")" << endl;
              break;
          }
          f2 =  615 + pow(6*k + 1, 2);
          if (f1 == f2) 
          {
              flag = false;
              cout << "(x, y)" << ":" << "(" << 6*k + 1 << "," << y << ")" << endl;
              cout << "(x, y)" << ":" << "(" << -(6*k + 1) << "," << y << ")" << endl;
              break;
          }
       }
    }
    return 0;
}
复制代码

代码解读

n 和 m是通过命令输入,来控制x和y的上限的。

flag 为找到解的标志。

外层循环的终止条件是表示式 k < n && !flag 的值为false。

这个解法跟大力出奇迹思路一样,只是先做了一点简单的推断,判定出x的形式,相比方法一,可以少67%的循环次数。

执行结果



全局优化

思路

  • 去掉一层循环。 我们可以先计算2^y 的结果,根据方程去推出算出x的值: x = sqrt(2^y - 615)。 x取整后,在根据取整的结果去计算 [x]^2 + 615是否跟2^y值相等。这里[x]表示对x取整。
  • 去掉pow调用,只改用一次sqrt。计算2^y的时候, 可以根据外层循环的次数来累乘2得出。
  • y肯定大于9, 不必做无谓的计算,所以从10开始。

代码


#include <iostream>
#include <cmath>
using namespace std;

int main(int argc, char* argv[])
{
    if (argc < 2) return -1;
    long n = atol(argv[1]);
    long long p = 512; //2^9 == 512
    for (long y = 10; y < n; y++)
    {
        p *= 2;
        long x = sqrt(p - 615);
        if (x *x + 615 == p) //判断x确实是整数且满足方程
        {
            cout << "(x, y) = " << "(" << x << "," << y << ")" << endl;
            cout << "(x, y) = " << "(" << -x << "," << y << ")" << endl;
        }
        break;
    }
        
    return 0;
}

### 代码解读

p 存储2^y 值,倒推x值, 取整后计算x^2 + 615,是否跟2^y相等。
本方法也不需要flag这种标志了,因为只有一层循环,直接break即可终止。

### 执行结果

复制代码

代码解读

减少一层循环,在循环内只有一次sqrt调用。理论上,应该比方法一和方法二都要高效。

执行结果



总结

三个方法中,显然方法三是比较优的方法。

本案例提升效率的方法:

  • 局部优化,譬如从数学角度先做优化
  • 全局优化,不但要从数学角度,而且逆向思维,从y出发导出x,再从x去验算y。
  • 避免都充循环
  • 在循环中尽量少用函数调用,可以多采用简答的加法和乘法。

必果学院

腾讯课堂必果学院是一个致力于C/C++/Python全栈学习的平台。必果学院提供从MFC/QT的客户端到linux服务器,嵌入式到物联网,游戏开发到游戏破解等一站式教学。适合0基础的对编程感兴趣初高中学生及以程序员为目标职业的在校大学生和初入职场不就亟待提升的初中级程序员。


相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码