HDU -7106 Function

本文主要探讨了一种基于数学优化的算法,用于寻找函数f(x)在特定区间内的最小值。通过对函数形式的分析,枚举可能的中间值g(x),并考虑函数的开口方向、对称轴等因素,确定了可能的最小值位置。通过C++实现,遍历所有可能情况,最终找到全局最小值。算法适用于解决类似问题,提高了求解效率。
摘要由CSDN通过智能技术生成

Function

1.因为g(x)只可能在1~54之间取值,所以枚举g(x),在确定g(x)的前提下寻找满足条件的x值。

2.f(x) = (agx+b)xx+(cgxgx+dgx)*x,只有四种情况:

(1)(a*gx+b) > 0开口朝上,最小值只可能在1或者n;

(2)(a*gx+b) < 0开口朝下,最小值只可能在1或者n或者对称轴上;

(3)(agx+b) = 0 && (cgxgx+dgx) > 0,一次函数且递增,最小值只可能在1处;

(4)(agx+b) = 0 && (cgxgx+dgx) > 0,一次函数且递减,最小值只可能在n处;

如果(agx+b) = 0 && (cgxgx+dgx) = 0,举例x=1即可。

解法:ans = min(ans, Ans(1));ans = min(ans, Ans(n)),枚举gx寻找对称轴并ans = min(ans, Ans(-b/2a))

/**
 * ID: W_208YE
 * LANG: C++11
 * PROG: ride
 */
#include <bits/stdc++.h>
#define ll long long
#define lld long double
#define pii pair<int, int>

using namespace std;

const int MOD = 1e9 + 7;
const int MAXN = 1e6;
const int MAXK = 1e6 + 10;
const int INF = 0x3f3f3f3f;

ll t, n, a, b, c, d;
vector<int> v[60];
ll base(ll x) {
    ll sum = 0;
    while (x) {
        sum += x % 10;
        x /= 10;
    }
    return sum;
}
void init(void) {
    for (int i = 1; i <= MAXN; ++i)
        v[base(i)].push_back(i);
}
ll Ans(ll x) {
    ll gx = base(x);
    return (a*gx+b)*x*x+(c*gx*gx+d*gx)*x;
}
void solve(void) {
    cin >> a >> b >> c >> d >> n;
    ll gx = INF, x, pos, ans = INF;
    ans = min(ans, Ans(1));
    ans = min(ans, Ans(n));
    for (int i = 1; i <= 54; ++i) {
        /*1.讨论满足gx == i的x的两端Ans值*/
        // upper_bound寻找大于n的第一个数,使得v[i][pos-1]是在v[i]中最接近n的数
        pos = upper_bound(v[i].begin(), v[i].end(), n) - v[i].begin();
        if (pos != 0) { // pos == 0, n小于v[i]中的数
            ans = min(ans, Ans(v[i][pos-1]));
        // if (n >= v[i][0]) // 没有必要,与pos!=0意思相同 
            ans = min(ans, Ans(v[i][0]));
        }
        /*2.此情况为一次函数,最小值只可能在1或n处取得,前面已经讨论*/
        if (a * i + b == 0) continue;
        /*3.讨论在满足gx==i的x与对称轴差值最小的x*/
        x = -(c*i*i+d*i)/(a*i+b)/2;
        if (x >= 1) { // x小于1时,只讨论1和n即可
            pos = lower_bound(v[i].begin(), v[i].end(), x) - v[i].begin();
            if (n >= x) {
                if (pos != v[i].size() && v[i][pos] <= n) 
                    ans = min(ans, Ans(v[i][pos]));
                if (pos != 0 && v[i][pos] <= n) 
                    ans = min(ans, Ans(v[i][pos-1]));
            }
        }
    }
    cout << ans << endl;
}
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0); 
    init();
    cin >> t;
    while(t--)
        solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值