题目:here
题目大意:给出CF[0]<0,CF[i]>0,i>0,求IRR(IRR>-1)令NPV = 0.
思路:设f(IRR) = NPV,这就变成了一个函数,稍微观察一下,可以发现当IRR∈(-1, +∞)的时候是单调递减的(好像是吧做完忘了),这样我们就可以二分答案0点了。当IRR无限接近-1的时候,f(IRR)→+∞(好像是吧),当 IRR→+∞时,f(IRR)→CF[0]<0,令left = -1、right = 1e5(我也不知道该取什么我随便取的然后AC了),随便二分一下就好。
PS:恩?说完了?那什么时候输出No和Too many啊?关于这个坑爹的问题,看完前面的分析,笔者完全不知道什么时候会出现这两个答案,于是妥妥地没将这两个东西写进代码然后AC了。这里还有一个 小技巧,题目的样例完全没有出现No和Too many这两种答案,很可能说明这两种答案都是不存在的。比如很多的题目说如果什么什么得不到答案就输出-1那样,它的样例大多都会有一个是输出-1的, 当然这不是绝对的……
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 using namespace std; 7 8 const int MAXN = 13; 9 const double EPS = 1e-4; 10 11 inline int sgn(double x) { 12 if(fabs(x) < EPS) return 0; 13 return x > 0 ? 1 : -1; 14 } 15 16 int CF[MAXN]; 17 int T; 18 19 double f(double IRR) { 20 double ret = CF[0], tmp = 1 + IRR; 21 for(int i = 1; i <= T; ++i) { 22 ret += CF[i] / tmp; 23 tmp = tmp * (1 + IRR); 24 } 25 return ret; 26 } 27 28 double solve() { 29 double ans = -2; 30 double L = -1, R = 1e5; 31 while(R - L > EPS) { 32 double mid = (R + L) / 2; 33 if(sgn(f(mid)) == 1) L = mid; 34 else R = mid; 35 } 36 return ans = L; 37 } 38 39 int main() { 40 while(scanf("%d", &T) != EOF) { 41 if(T == 0) break; 42 for(int i = 0; i <= T; ++i) scanf("%d", &CF[i]); 43 //double t; while(cin>>t) cout<<f(t)<<endl; 44 printf("%.2f ", solve()); 45 } 46 }