HDU7106 Function(三分)

目录

Description

\(f(x)=Ax^2g(x)+Bx^2+Cxg^2(x)+Dxg(x)\), 其中 \(g(x)\) 为 \(x\) 的数位之和,求 \(f(x)\) 的最小值(\(1<=x<=N\))

State

\(1<=T<=10^4\)

\(0<=|A|<=10^3,0<=|B|,|C|,|D|<=10^6,1<=N<=10^6\)

Input

2
1 2 3 4 100
4 3 2 1 100

Output

10
10

Solution

看到 \(x<=N\) 的条件,一看 \(N\) 又不大,要不是有 \(T\) 在那里摆着就可以枚举 \(g(x)=[1,54]\) 的所有情况了

这个式子已经确定是一个二次函数了,求最小值,三分求凹函数最小值,当然需要特判掉不是二次函数以及开口向下的情况


Code

    int n, m, _, k;
    //int a[N];
    vector<int> v[60];

int calc(int x)
{
    int ans = 0;
    while(x) ans += x % 10, x /= 10;
    return ans;
}

void init()
{
    for(int i = 1; i <= 1e6; i ++){
        v[calc(i)].pb(i);
    }
}

ll check(ll x, ll A, ll B)
{
    return A * x * x + B * x;
}

signed main()
{
    //IOS;
    ll a, b, c, d;
    init();
    rush(){
        sll2(a, b); sll2(c, d); sd(n);
        ll minn = 6e18;
        for(int i = 1; i <= 54; i ++){
            if(v[i].size() == 0) continue;
            ll A = a * i + b, B = c * i * i + d * i;
            int l = 0, r = upper_bound(v[i].begin(), v[i].end(), n) - v[i].begin() - 1;
            ll ans = 6e18;
            if(l > r) continue;
            if(A <= 0){
                ans = min(check(v[i][l], A, B), check(v[i][r], A, B));
                minn = min(ans, minn);
                continue;
            }   
            while(r >= l){
                int midl = l + (r - l) / 3;
                int midr = r - (r - l) / 3;
                if(check(v[i][midl], A, B) < check(v[i][midr], A, B)){
                    r = midr - 1;
                    ans = min(ans, check(v[i][midl], A, B));
                }
                else{
                    l = midl + 1;
                    ans = min(ans, check(v[i][midr], A, B));
                }
            }
            minn = min(minn, ans);
        }
        pll(minn);
    }
    //PAUSE;
    return 0;
}
上一篇:POJ1961 KMP算法


下一篇:c++单元测试框架Catch2的简单使用