天天看点

NOI题库_微积分_NOI2001反正切函数的应用

对于那个式子,我们可以展开得到(a*b+a*c)=b*c-1 => b=(a*c+1)/(c-a)   => b+c=(c*c+1)/(c-a)

很显然  a不等于c

那么我们可以构造一个函数 f(c)=b+c=(c*c+1)/(c-a), 要求极值 ,

那么我们可以先求导, f(x)的导数g(x)=c*c-2*a*c-1

因为极值出的导数为零,那么就相当于是一个一元二次方程.

此时c=a + sqrt(a*a+1)或a - sqrt(a*a+1) 分析导数图像可以得出f(c)最小时c=a + sqrt(a*a+1).

但是我们取到的是可能无理数啊那怎么办?

在第一象限内可以看做是 f(c) 单峰函数(导数另一个零点在第二象限)那么我们可以同时递增和递减 c 然后验证b是否为整数 找到的第一个可行解即为最优解

听CA爷说貌似还可以来枚举因数?反正我不会...   %%%%CA爷

附代码:

#include<cstdio>

#include<iostream>

#include<cstring>

#include<cmath>

using namespace std;

int a,b,c;

int Check(double c)

{

    if(a==c )

       return -1;

double b=(a*c+1)/(c-a);

if(c<=0||b<=0)

  return -1;

    int b_i=(int)b,c_i=(int)c;

return a*(c_i+b_i)!=(c_i*b_i-1)?-1:b_i+c_i;

}

int main()

{

double Mid;

scanf("%d",&a);

Mid=(2.0*a+sqrt(4.0*a*a+4.0))/2.0; 

int ans=Check((int)Mid);

    int tp=-1,y;

    int b=((int)Mid-1),c=b+2;

do{

y=Check(b);

if(y!=-1)

 tp=y;

y=Check(c);

if(y!=-1)

 if(tp!=-1)

  tp=min(tp,y);

 else tp=y;

else;

if(tp!=-1)

ans=min(tp,ans);

if(ans==-1)ans=tp;

 b--;c++;

}while(ans==-1);

printf("%d\n",ans);

return 0;

}