UVA 11881 Internal Rate of Return(数学+二分)
In finance, Internal Rate of Return (IRR) is the discount rate of an investment when NPV equals zero. Formally, given T, CF0, CF1, ..., CFT, then IRR is the solution to the following equation:
![$\displaystyle {CF_1 \over {1+IRR}}$](http://uva.onlinejudge.org/external/118/11881img1.png)
![$\displaystyle {CF_2 \over {(1+IRR)^2}}$](http://uva.onlinejudge.org/external/118/11881img2.png)
![$\displaystyle {CF_T \over {(1+IRR)^T}}$](http://uva.onlinejudge.org/external/118/11881img3.png)
Your task is to find all valid IRRs. In this problem, the initial cash-flow CF0 < 0, while other cash-flows are all positive (CFi > 0 for all i = 1, 2,...).
Important: IRR can be negative, but it must be satisfied that IRR > - 1.
Input
There will be at most 25 test cases. Each test case contains two lines. The first line contains a single integer T ( 1T
10), the number of positive cash-flows. The second line contains T + 1 integers: CF0, CF1,CF2, ..., CFT, where CF0 < 0, 0 < CFi < 10000 ( i = 1, 2,..., T). The input terminates by T = 0.
Output
For each test case, print a single line, containing the value of IRR, rounded to two decimal points. If noIRR exists, print ``No" (without quotes); if there are multiple IRRs, print ``Too many"(without quotes).
题目大意:给出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的,当然这不是绝对的……
代码(15MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", solve()); 45 } 46 }