T1 立方数
题目
【题目描述】
作为XX战队的狂热粉丝,MdZzZZ看到了自己心仪的队伍在半决赛落败,顿时心灰意冷。看着自己手中的从黄牛那里抢来的天价总决赛门票,MdZzZZ觉得去鸟巢已经没有意义了,于是他决定去跳“水立方”。在他准备进“水立方”体育馆时,一位大妈拦住了他的去路,并产生了一下对话:
大妈:“年轻人我看你印堂发黑,恕我冒昧直言,此去一行怕是会有什么不测。”
MdZzZZ:“大妈别拦我,我要跳水立方发泄一下!”
大妈:“年轻人,做事要三思而后行,你知道这水立方最著名的是什么吗?”
MdZzZZ:“不知...”
大妈:“这水立方最有名的是‘立方数’!”
MdZzZZ:“哦?”
大妈:“别急,听我细细道来。‘立方数’就是,如果一个数可以被写作是一个正整数的3次方,则这个数就是立方数。例如1,8,27就是最小的3个立方数。”
MdZzZZ:“……”
大妈:“当然,想要在这水立方中来去自如,你需要知道‘立方差数’!”
大妈:“若一个数可以被写作是两个立方数的差,则这个数就是‘立方差数’,例如7(8-1),26(27-1),19(27-8)都是立方差数。如果你能够判断随便一个数是不是‘立方差数’,那么你就可以真正地在这一片小天地中当一条无忧无虑的小鱼...”
未等MdZzZZ反应过来,大妈以飘然远去,留下他一个人在那边细细思索。那么现在你的问题来了,你需要帮助MdZzZZ解决这个问题。
现在给定一个数P,MdZzZZ想要知道这个数是不是立方差数。
当然你有可能随机输出一些莫名其妙的东西,因此MdZzZZ有T次询问~
这个问题可能太难了…… 因此MdZzZZ规定P是个质数!
【输入格式】
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。
【输出格式】
输出T行,对于每个数如果是立方差数,输出“YES”,否则输出“NO”。
【输入样例】
5
2
3
5
7
11
【输出样例】
NO
NO
NO
YES
NO
【数据规模】
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^12,T<=100。
解析
嗯......题目很长,去掉废话,实际上就是要求质数p是不是立方差数(立方数即为a3-b3(a,b均为正整数,且a≠b)。
我们尝试化简一下a3-b3=p这个式子,可以得到(a-b)(a2+ab+b2)=p,因为p是质数,根据质数的定义(只有1和它本身是它的因数)可以得到,a-b与a2+ab+b2其中一个为1,
很显然a2+ab+b2不为1(因为a与b为互不相等的正整数),所以a-b=1,移项得a=b+1,带入a3-b3=p,得
(b+1)3-b3=p,即b3+3b2+3b+1-b3=p,化简并移项得3b2+3b+1-p=0,显然,这是一个一元二次方程,解这个方程可得,
b=(-3±sqrt(12p-3))/6(sqrt为求根号函数),由于b是正整数,所以如果-3±sqrt(12p-3)可以整除6的话,p就是立方差数。
由于p≤10^12,所以要记得开long long(本蒟蒻就是没开long long少了40分QAQ)。
Code
#include <algorithm> #include <iostream> #include <cstdio> #include <cmath> using namespace std; long long read() { long long num=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { num=(num<<1)+(num<<3)+ch-'0'; ch=getchar(); } return num*w; } int T; long long p; double a; int main() { //freopen("cubicp.in","r",stdin); //freopen("cubicp.out","w",stdout); T=read(); while(T--) { p=read(); a=(sqrt(12*p-3)-3)-(long long)(sqrt(12*p-3)-3); if(a==0&&(long long)(sqrt(12*p-3)-3)%6==0) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; //fclose(stdin); //fclose(stdout); }