题目:
题目大意:给出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 #include2 #include 3 #include 4 #include 5 #include 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< <