【三分】

【三分】

单峰函数最大值/单谷函数最小值
凹函数/凸函数

思路

image

模版代码

整数域三分

求凸点

while (l < r) {
    int mid = (l + r) / 2;
    if (check(mid) >= check(mid + 1)) r = mid;
    else l = mid + 1;
}

求凹点

while (l < r) {
    int mid = (l + r) / 2;
    if (check(mid) <= check(mid + 1)) r = mid;
    else l = mid + 1;
}

实数域三分

求凸点

while(abs(r-l)>eps){//左右区间差值需要是一个很小的数
	ld mid=(l+r)/2;
	ld lmid=mid-eps;
	ld rmid=mid+eps;
	if(f(lmid)<f(rmid)) l=mid;//说明左区间需要被舍去
	else r=mid;//说明右区间需要被舍去
}
ld ans=(l+r)/2;

求凹点

while(abs(r-l)>eps){//左右区间差值需要是一个很小的数
	ld mid=(l+r)/2;
	ld lmid=mid-eps;
	ld rmid=mid+eps;
	if(f(ei,lmid)<f(ei,rmid)) r=mid;//说明左区间需要被舍去
	else l=mid;//说明右区间需要被舍去
}
ld k=(l+r)/2;

限制次数

//找凹点
ld l = -1e9, r = 1e9;
for (int t = 1; t <= 100; t++) {
    ld mid1 = (l * 2 + r) / 3;
    ld mid2 = (l + r * 2) / 3;
    if (judge(mid1) < judge(mid2)) {
        r = mid2;
    } else {
        l = mid1;
    }
}
cout << l << endl;
//找凸点
ld l = -1e9, r = 1e9;
for (int t = 1; t <= 100; t++) {
    ld mid1 = (l * 2 + r) / 3;
    ld mid2 = (l + r * 2) / 3;
    if (judge(mid1) > judge(mid2)) { 
        r = mid2;
    } else {
        l = mid1;
    }
}
cout << l << endl;

模版题

https://www.luogu.com.cn/problem/P3382

题目大意

image

代码

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef pair<int,int> PII;
ll abss(ll a){return a>0?a:-a;}
ll max_(ll a,ll b){return a>b?a:b;}
ll min_(ll a,ll b){return a<b?a:b;}
bool cmpll(ll a,ll b){return a>b;}
const int INF_INT=0x3f3f3f3f;
const ll INF_LL=0x3f3f3f3f3f3f3f3f;
const int N=20;
const ld eps=0.0000001;
int n;
ld l,r;
ld x[N];
ld f(ld a){
    ld aa=1;
    ld ans=0;
    for(int i=n;i>=0;i--){
        ans=ans+aa*x[i];
        aa=aa*a;
    }
    return ans;
}
void solve(){
    cin>>n;
    cin>>l>>r;
    //cout<<n<<endl;
    for(int i=0;i<=n;i++){
        cin>>x[i];
    }
    while(abs(r-l)>eps){
        ld mid=(l+r)/2;
        ld lmid=mid-eps;
        ld rmid=mid+eps;
        if(f(lmid)<f(rmid)) l=mid;
        else r=mid;
    }
    ld ans=(l+r)/2;
    cout<<fixed<<setprecision(6)<<ans<<endl;
}


signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--) solve();
    return 0;
}

【题目积累】

【对勾函数】502 Bad Gateway

https://codeforces.com/gym/105358/problem/L

题目大意

image

思路

image

代码

struct Fraction {
private:
    i64 numerator;   // 分子
    i64 denominator; // 分母

    // 化简分数
    void reduce() {
        if (denominator == 0) {
            throw invalid_argument("分母不能为零");
        }

        // 确保分母为正数
        if (denominator < 0) {
            numerator *= -1;
            denominator *= -1;
        }

        // 约分
        i64 commonDivisor = gcd(numerator, denominator);
        if (commonDivisor != 0) {
            numerator /= commonDivisor;
            denominator /= commonDivisor;
        }

        // 分子为零时,分母固定为1
        if (numerator == 0) {
            denominator = 1;
        }
    }

public:
    // 构造函数
    Fraction(i64 num = 0, i64 den = 1) : numerator(num), denominator(den) {
        reduce();
    }

    // 拷贝构造函数
    Fraction(const Fraction& other) : numerator(other.numerator), denominator(other.denominator) {}

    // 判断是否为整数:分母为1时是整数
    bool isInteger() const {
        return denominator == 1;
    }

    // 加法运算
    Fraction operator+(const Fraction& other) const {
        i64 newDenominator = denominator * other.denominator;
        i64 newNumerator = numerator * other.denominator + other.numerator * denominator;
        return Fraction(newNumerator, newDenominator);
    }

    // 减法运算
    Fraction operator-(const Fraction& other) const {
        i64 newDenominator = denominator * other.denominator;
        i64 newNumerator = numerator * other.denominator - other.numerator * denominator;
        return Fraction(newNumerator, newDenominator);
    }

    // 乘法运算
    Fraction operator*(const Fraction& other) const {
        i64 newNumerator = numerator * other.numerator;
        i64 newDenominator = denominator * other.denominator;
        return Fraction(newNumerator, newDenominator);
    }

    // 除法运算
    Fraction operator/(const Fraction& other) const {
        if (other.numerator == 0) {
            throw invalid_argument("除数不能为零");
        }
        i64 newNumerator = numerator * other.denominator;
        i64 newDenominator = denominator * other.numerator;
        return Fraction(newNumerator, newDenominator);
    }

    // 赋值运算符
    Fraction& operator=(const Fraction& other) {
        if (this != &other) {
            numerator = other.numerator;
            denominator = other.denominator;
        }
        return *this;
    }

    // 输出运算符重载(友元函数)
    friend ostream& operator<<(ostream& os, const Fraction& f) {
        if (f.denominator == 1) {
            os << f.numerator;
        } else {
            os << f.numerator << " " << f.denominator;
        }
        return os;
    }

    // 获取分子
    i64 getNumerator() const { return numerator; }
    
    // 获取分母
    i64 getDenominator() const { return denominator; }
};
const int N=3e5+10;
i64 t;
ld check(i64 x){
    ld res=((ld)x-1.0)/2.0+(ld)t/ld(x);
    return res;
}
void solve(){
    cin>>t;
    i64 l=0,r=t;
    while (l < r) {
        i64 mid = (l + r) / 2;
        if (check(mid) <= check(mid + 1)) r = mid;
        else l = mid + 1;
    }
    Fraction f1(l-1LL,2LL);
    Fraction f2(t,l);
    Fraction ans=f1+f2;
    cout<<ans;
    if(ans.isInteger()) cout<<" "<<1;
    cout<<endl;
}
posted @ 2025-06-06 18:46  White_ink  阅读(32)  评论(0)    收藏  举报