A题:
方法一:一元二次方程求解,但是会有精度误差,+1个点特判一下。
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; ll t; ll x,y,z; int main() { //freopen("in.txt","r",stdin); ll n; scanf("%lld%lld",&n,&t); ll ans = 0; for(ll i = 1; i <= n; i++) { scanf("%lld%lld%lld",&x,&y,&z); ll cnt; if(y==0&&z==0) continue; if(z==0) cnt = t/(x+y); else if(z!=0) { ll sq = ((x+y)-z/2)*((x+y)-z/2) + 2*z*t; sq = sqrt(sq) + z/2 - (x+y); cnt = (sq/z); } if((cnt+1)*(x+y)+(cnt+1)*cnt/2*z<=t) cnt++; ll tmp = cnt*(x+y) + cnt*(cnt-1)/2*z; if(t-tmp>=x) { ans += (t-(cnt+1)*x); } else { ans +=(t-cnt*x-(t-tmp)); } } cout<<ans<<endl; return 0; }
方法二:二分
二分是很坑的,二分上界是2e9,中间结果爆数据类型。大佬的解法是处理一下mid,2e9 >= (mid-1)*mid/2*z,移项一下。
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,t,ans,res; ll x,y,z; int main() { scanf("%lld%lld",&n,&t); for(ll i = 1ll; i <= n; i++) { scanf("%lld%lld%lld",&x,&y,&z); ll l = 1,r= 2000000000; ans = 0; while(l<=r) { ll mid = (l+r)>>1; if(2000000000/mid>=(mid-1)*z/2&&(1ll*(x+y)*mid+1ll*(mid-1)*mid/2*z)<=t) { l = mid+1; ans = mid; } else r = mid - 1; } ll tmp = (1ll*(x+y)*ans+1ll*(ans-1)*ans/2*z); ll tt = 0; tt += tmp - 1ll*ans*x; if(x<t-tmp) tt+=t-tmp-x; res+=tt; } printf("%lld\n",res); return 0; }
D题:
当时脑子短路,不知道为什么要二分t,然后b全部都减t,处理a变与不变。当然感觉也是可以的,但是硬是90%。无语了~~~
看了题解,简直吐血~
贪心,先把a给变了,然后对应的max(0,b[i]-a[i]);
看来以后得大胆的贪心~~~
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 200005; ll a[MAXN],b[MAXN]; int main() { int n,x; ll y; cin>>n>>x>>y; for(int i = 0; i < n; i++) scanf("%lld",&a[i]); for(int i = 0; i < n; i++) scanf("%lld",&b[i]); sort(a,a+n); sort(b,b+n); for(int i = 0; i < x; i++) if(a[i]<y) a[i] = y; sort(a,a+n); ll ans = 0; for(int i = 0; i < n; i++) { ans = max(ans,b[i]-a[i]); } printf("%lld\n",ans); return 0; }
时间: 2024-11-02 14:00:09