Luogu P1925 最大划分乘积

题意

略。

题解

简单题。

容易看出 \(f(x)=\left(\dfrac{n}{x}\right)^x\),考虑求这个东西的极值,看一眼发现是取对数求导法,那么有

\[\ln f(x)=x\ln n-x\ln n \]

所以

\[(\ln F(x))^\prime=\ln n-\ln x-1 \]

于是

\[F^{\prime}(x)=F(x)(\ln F(x))^{\prime}=\left(\frac{n}{x}\right)^x(\ln n-\ln x-1) \]

考虑求导数的零点。注意到 \(f(x)=\left(\dfrac{n}{x}\right)^x\) 没有零点,所以零点只可能存在于右边的括号中,也即 \(x=\dfrac{n}{e}\)

由于最终的 \(x\) 只能取整数,所以极值只可能在 \(\left\lfloor\dfrac{n}{e}\right\rfloor\)\(\left\lceil\dfrac{n}{e}\right\rceil\) 取到,比较两个值可以直接比较对数大小。接下来就很平凡了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
typedef long double db;
const ll MAXN=2e5+51;
const db E=exp(1.0);
ll n,res,lx,rx,g;
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
inline db lnf(ll n,ll x)
{
    return log(1.0L*n)*x-log(1.0L*x)*x;
}
inline ll calc(ll n)
{
    lx=n/E,rx=n/E+1,lx=lnf(n,lx)>lnf(n,rx)?lx:rx,g=__gcd(n,lx),lx/=g;
    while(lx%2==0)
    {
        lx/=2;
    }
    while(lx%5==0)
    {
        lx/=5;
    }
    return lx==1?-n:n;
}
int main()
{
    n=read();
    for(register int i=5;i<=n;i++)
    {
        res+=calc(i);
    }
    printf("%d\n",res);
}
posted @ 2020-11-04 10:14  Karry5307  阅读(437)  评论(0编辑  收藏  举报