题目
题目描述
我妻蛤乃给你出了一道送命题:
黄梅时节家家雨,青草池塘处处蛙~
有n只青蛙,第i只青蛙会每过xi秒会连续叫yi秒。然而由于青蛙的寿命在增加,所以从第二次开始每次休息结束后这只青蛙连续叫的时间会增加zi秒。
给定n只青蛙,每一只的xi,yi,zi,以及时间t,求在前t秒中,所有青蛙共叫了多少秒。
输入输出格式
输入格式:
第一行两个数n和t之后n行,第i+1行每行三个非负整数xi,yi,zi
输出格式:
一行一个数表示答案
输入输出样例
输入样例#1:
8 10 9 1 1 1 9 9 4 1 0 2 3 3 1 0 0 1 4 0 9 2 5 1 2 1
输出样例#1:
34
输入样例#2:
1 233333 233 233 233
输出样例#2:
223081
输入样例#3:
10 100000000 1 0 0 1 0 5 1 2 2 1 2 8 1 3 0 1 5 0 1 5 2 1 5 5 1 7 0 1 8 3
输出样例#3:
845787522
说明
样例#4,#5见下发的文件
【子任务】
子任务会给出部分测试数据的特点。 如果你在解决题目中遇到了困难, 可以尝试只解决一部分测试数据。
每个测试点的数据规模及特点如下表:
对于100%的数据,n <= 100000 , t <= 2000000000,x + y + z > 0
0 <= x , y , z <= 2000000000
【说明】
【样例1说明】
每只青蛙分别叫了1,9,2,6,0,8,1,7秒
【样例2说明】
那只青蛙叫了223081秒
【样例3说明】
每只青蛙分别叫了0,99993675,99990000,99994999,75000000,83333333,99990002,99993676,87500000,99991837秒
思路:
第一题看似是一道水题。/假的
最后写得这个方法呢,是利用二分答案算青蛙叫的次数,然后用 t 减去。
注意:
- 二分的时候两个 2e9 加起来会爆掉 int 的……
- 如果这个青蛙叫的时间会增长,那么二分的上界是 O(sqrt(t)) 级别的。
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 #include <cmath> 7 using namespace std; 8 unsigned int n,t; 9 long long ans; 10 inline long long cal( long long x , long long y , long long z , long long k ) 11 { 12 return k * 1ll * ( x + y ) + k * 1ll * ( k + 1 ) / 2 * z; 13 } 14 inline long long cal() 15 { 16 long long x , y , z , l = 1 , r = t , ans = 0 , mid; 17 cin >> x >> y >> z; 18 if( z ) r = sqrt( 2 * t / z ) + 233333/*忽略它*/; 19 y -= z; 20 while( l <= r ) 21 { 22 mid = (l + r) >> 1; 23 if(mid * 1ll * ( x + y ) + mid * 1ll * ( mid + 1 ) / 2 * z <= t) 24 { 25 l = mid + 1; 26 ans = mid; 27 } 28 else 29 r = mid - 1; 30 } 31 return ans * 1ll * x + min(t-cal(x,y,z,ans),1ll*x); 32 // 33 } 34 int main() 35 { 36 //freopen("test.in","r",stdin); 37 //freopen("test.out","w",stdout); 38 cin >> n >> t; 39 for (unsigned int i=1; i<=n; i++) 40 { 41 int thisFrog = cal(); 42 //cout << thisFrog << endl; 43 ans += t-thisFrog; 44 } 45 cout << ans << endl; 46 return 0; 47 }