3 条题解
-
2
先对原式进行化简:
$$\begin{aligned}X&=a^3+a^2b+ab^2+b^3\\&=a^2(a+b)+b^2(a+b)\\&=(a+b)(a^2+b^2)\end{aligned}$$没啥用,只是方便写代码而已,完全可以不花简。
我们让 ,可以得到当 时 最大,此时原式化简为 。而 , 时原式等于 ,大于 ,因此 最大只会到 。
考虑枚举 ,明显 固定时 越大原式越大,具有单调性,可以二分 。 最小为 , 时原式刚好等于 ,因此二分 时左边界为 ,右边界为 。
最终时间复杂度为 ,其中,可以通过。
还有一个小优化,如果枚举到当前 时 已经大于等于 ,就可以直接 了。
#include<bits/stdc++.h> using namespace std; #define int long long int n,ans; bool check(int a,int b) { return (a+b)*(a*a+b*b)>=n; } signed main() { scanf("%lld",&n);ans=1e18; for(int a=0;a<=629961;a++) { if(4*a*a*a>=ans)break; int l=a-1,r=1e6,mid,b=1e6; while(l+1<r) { mid=(l+r)>>1; if(check(a,mid))r=mid,b=min(b,mid); else l=mid; } ans=min(ans,(a+b)*(a*a+b*b)); } printf("%lld\n",ans); return 0; }然后其实可以根据 来计算 的最大值和二分 时的右边界,进一步优化。
#include<bits/stdc++.h> using namespace std; #define int long long int n,ans; bool check(int a,int b) { return (a+b)*(a*a+b*b)>=n; } signed main() { scanf("%lld",&n); int mxa=pow(n/4,1/3); while(mxa*mxa*mxa*4<n)mxa++; ans=mxa*mxa*mxa*4; int mxb=pow(n,1/3); while(mxb*mxb*mxb<n)mxb++; for(int a=0;a<=mxa;a++) { if(4*a*a*a>=ans)break; int l=a-1,r=mxb,mid,b=mxb; while(l+1<r) { mid=(l+r)>>1; if(check(a,mid))r=mid,b=min(b,mid); else l=mid; } ans=min(ans,(a+b)*(a*a+b*b)); } printf("%lld\n",ans); return 0; } -
2
题目大意
题目描述清楚,不做赘述
解题思路
定义 ,则有:
$$=(a+1)^{3}+(a+1)^{2}b+(a+1)b^{2}+b^{3}-a^{3}+a^{2}b+ab^{2}+b^{3}$$题目要求 ,所以 具有单调性,二分 双指针都能过
双指针代码
#include<bits/stdc++.h> using namespace std; #define int long long int n; int check(int a,int b){ return (a*a+b*b)*(a+b); } signed main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>n; int l=0,r=1e6; int ans=1e18; while(l<=r){ if(check(l,r)>=n)ans=min(check(l,r),ans),r--; else l++; } cout<<ans<<'\n'; return 0; }二分代码
#include<bits/stdc++.h> using namespace std; #define int long long int n; int check(int a,int b){ return (a*a+b*b)*(a+b); } signed main(){ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>n; int l=0,r=1e6; int k=0; while(l<=r){ int mid=(l+r)>>1; if(mid*mid*mid>=n)k=mid,r=mid-1; else l=mid+1; } int ans=1e18; for(int i=0;i<=k;i++){ int l=i,r=k; while(l<=r){ int mid=(l+r)>>1; if(check(i,mid)>=n)ans=min(ans,check(i,mid)),r=mid-1; else l=mid+1; } } cout<<ans<<'\n'; return 0; } -
0
ezkm
思路
首先因为,而题目的式子是三次的,不难发现要求的肯定不会超过。然后也不难发现如果是固定的,原式的值随的增大而增大,符合二分的条件。因此不妨枚举的值,然后二分的值,不断更新答案即可。
AC代码
#include<bits/stdc++.h> #define int long long using namespace std; signed main() { int n;scanf("%lld",&n); int l=0,r=1000000,sqr; while(l<=r) { int mid=l+r>>1; if(mid*mid*mid>=n)r=mid-1,sqr=mid; else l=mid+1; } int ans=1ll<<60; for(int i=0;i<=sqr;i++) { int l=i,r=sqr; while(l<=r) { int mid=l+r>>1; if(mid*mid*mid+i*i*i+i*i*mid+i*mid*mid>=n)r=mid-1,ans=min(ans,mid*mid*mid+i*i*i+i*i*mid+i*mid*mid);//一坨大的 else l=mid+1; } } printf("%lld\n",ans); return 0; }
- 1
信息
- ID
- 12440
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 50
- 已通过
- 11
- 上传者