D

Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020
在这里插入图片描述
并且, 其中的a如果不等于0 , 那么肯定a >= 1 , 如果在t 时间访问完ai
那么下一个访问完花费时间是
( t + 1 ) * aj + bj + t , 这就相当于两倍的t还多 , 照这样加些去, 会变成4t , 8t ,几何式增长, 所以只要30次就够了,
然后考虑到还有a=0的, 所以呢, 如果访问了i个a >= 1 的, 再找到符合T时间a=0超时就行了,二分查找,两者相加<=t , 并且两者相加求最大

#include <bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<ll , ll> Pair ;
const int N = 2e5 + 10 ;
Pair a[N] ;
#define f first
#define s second
ll c[N] , dp[44] ;
bool cmp(Pair a , Pair b)
{
  return a.f * (b.s + 1) >  b.f * (a.s + 1) ;
}
int main()
{
  ll n , t ;
  scanf("%lld%lld" , &n , &t) ;
  int cnt1 = 0 , cnt2 = 0 ;
  for(int i =1 ; i <= n ;i ++)
   {
     ll x , y ;
     scanf("%lld%lld" , &x , &y) ;
     if(x == 0) c[++ cnt1] = y + 1 ;
     else a[++ cnt2] = {x , y} ;
   }
   sort(a + 1 , a + cnt2 + 1 , cmp) ;
   sort(c + 1 , c + cnt1 + 1) ;
   for(int i = 0 ;i <= 30 ;i ++) dp[i] = t + 1 ;
   dp[0] = 0 ;
   for(int i = 1; i <= cnt2 ;i ++)
    for(int j = 30 ;j > 0 ;j --)
     dp[j] = min(dp[j] , (dp[j - 1] + 1) * (a[i].f + 1) + a[i].s) ;
  int ans = 0;
  for(int i = 1; i <= cnt1 ; i ++) c[i] += c[i - 1] ;
  for(int i = 0 ;i <= 30 ;i ++)
   {
     if(dp[i] > t) continue ;
     int j = 0 ;
     if(cnt1)
      j = upper_bound(c + 1 , c + cnt1 + 1 , t - dp[i]) - c - 1 ;
    ans= max(ans , j + i) ;

   }
   cout << ans << endl ;
  return 0 ;
}

每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
原文地址:https://www.cnblogs.com/spnooyseed/p/12870854.html