2021暑假多校训练3 E Math

博客解析了一道数学与编程相结合的题目,涉及数对(x, y)的寻找,其中x和y需满足特定的数学关系。通过韦达定理和循环迭代的方法,找到所有可能的数对,并用C++实现算法。错误代码与正确代码的对比揭示了对循环条件理解的重要性,强调了细节决定成败。
摘要由CSDN通过智能技术生成

 

 题目大意:首先给出一个数t表示样例的数目,下面的t行,每行有一个数n,要求我们求出满足上面式子的数对(x,y)的数量,其中1<=x<=y<=n。

题目解析:通过打表我们可以发现,当y=x^3时,以上式子始终满足。打表结果如下:

 x^2 + y^2 = k(xy + 1) // k是正整数
⇒ y^2 - kxy - k + x^2 = 0 // (1)
可以将x看成一个固定的值。
由韦达定理有 y1 + y2 = kx
对于一对满足条件的(x, y),有一对(x, kx - y)也满足条件。
所以(y, x)也满足条件,此时y是固定的,有(y, ky - x)条件。
对于上面打表找出的特例:(x,x^3)带入(1)式,得到 k = x^2。(以上推导来自一篇大佬博客:(144条消息) 2021牛客暑期多校训练营3-E(Math)_sweetheart7-7的博客-CSDN博客

所有就有了:
(x, x^3)
(x^3, x^5 - x)……

这样无线循环下去,直到当前数对的y超出给定范围。

在写代码的时候,自己在实现上出现了错误。

先上错误代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> 
using namespace std;
const int N =2e6+10;
long long ans[7001000];
int main()
{
	int cnt=0;
	ans[cnt++]=1;
	for(long long i=2;i<=1e6;i++)
	{
		long long x=i,y=i*i*i,k=i*i;
		while(y<=(1e18+x)/k)//k*y-x<=1e18
		{
			ans[cnt++]=y;
			long long temp=k*y-x;
			x=y;
			y=temp;//y>(1e18+x)/k && y valid
		}
	}
	sort(ans,ans+cnt);
	for(int i=1000;i<=10100;i++){
		cout<<ans[i]<<endl;
	}
	int t ;
	cin>>t;
	while(t--)
	{
		long long n;
		cin>>n;
		cout<<upper_bound(ans,ans+cnt,n)-ans<<endl;
	}
	return 0;
}

下面是正确代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> 
using namespace std;
long long ans[7001000];//这里尽量开大一点,不然很容易就会RE 
int main()  
{
	int cnt=0;
	ans[cnt++]=1;
	for(long long i=2;i<=1e6;i++)
	{
		long long x=i,y=i*i*i,k=i*i;
		ans[cnt++]=y;
		while(y<=(1e18+x)/k)
		{
			long long temp=k*y-x;
			x=y;
			y=temp;
			ans[cnt++]=y;
		}
	}
	sort(ans,ans+cnt);
	int t ;
	cin>>t;
	while(t--)
	{
		long long n;
		cin>>n;
		cout<<upper_bound(ans,ans+cnt,n)-ans<<endl;
	}
	return 0;
}

下面来比较一下这两份代码的不同之处:

错误:

正确: 

 这里考验的就是我们对while循环中判断条件的理解了,这里判断条件是怎么来的呢?它是根据式子:k*y-x<=1e18变形得来的,也就是说此时我们是把上一个状态的y当作当前状态的x来看,如果该条件满足,我们就应该将当前状态的y'=k*y-x加入数组中,而错误代码的意思是,拿当前状态的y'(上一个状态的y),判断下一个状态的y',如果满足条件就将当前状态的y'加入数组之中,这显然是不对的,因为下一个状态不合法,但是当前状态是合法的,如果没有加进去一定会导致答案出错。这里纠结调了好久就没有发现这个错误,还好队友给力帮我找到了这处bug。

### 回答1: 这段代码中有一个语法错误,应该在代码末尾加上分号。另外,由于是计算圆的面积,应该是乘号而不是加号。正确的代码应该是: ``` import math S = math.pi * 3 * 3; ``` 或者可以将分号省略: ``` import math S = math.pi * 3 * 3 ``` ### 回答2: 导入了math库后,通过math.pi可以获取到π的值。在代码中,S = math.pi*3*3表示计算了半径为3的圆的面积,并将结果赋给了变量S。 首先,math.pi表示圆周率π的值,它是一个浮点数。使用math.pi*3*3,我们可以计算出半径为3的圆的面积。根据圆的面积公式,圆的面积等于π乘以半径的平方。 其中,半径为3,即表示圆的半径长度为3。然后将该半径的平方即3*3=9,再乘以π,即可计算出圆的面积。 因此,S = math.pi*3*3的结果即为该圆的面积。根据算式计算,S的值应为圆的面积,即9π。 需要注意的是,由于math.pi返回的是浮点数,所以计算结果也是浮点数。如果需要将结果转换为整数,可以使用int()函数来实现。 ### 回答3: 首先通过导入math模块,我们可以使用其中的math.pi常量来表示圆周率π。接着,我们将圆的半径设置为3,即r = 3。然后,使用圆的面积公式S = πr^2计算圆的面积。 根据已经定义的半径r和math.pi常量,我们可以将圆的面积计算为: S = math.pi * r^2 = math.pi * 3^2 = math.pi * 9 这里的^表示乘方运算,即3的平方。 最后,将计算得到的结果输出: S = math.pi * 9 经过简化计算,圆的面积S约等于28.27。 所以,通过使用math模块中的math.pi常量和给定的半径,可以得到圆的面积S约为28.27。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值