HDU7106/2021中国大学生程序设计竞赛(CCPC)- 网络选拔赛 1007. Function(整数三分)

Problem Description

Let's define the sum of all digits in x as g(x). For example, g(123)=1+2+3=6. Give you a function:

f(x)=Ax2g(x)+Bx2+Cxg2(x)+Dxg(x)

Find the minimum value of f(x), where x is an integer and 1≤x≤N.

Input

This problem contains multiple test cases.

The first line of the input contains an integer T(1≤T≤104), representing the number of test cases.

Each of the next T lines contains five integers A,B,C,D,N(0≤|A|≤103,0≤|B|,|C|,|D|≤106,1≤N≤106) indicating a test case.

Output

For each test case output an integer, denoting the answer.

Sample Input

2
1 2 3 4 100
4 3 2 1 100

Sample Output

10
10

比赛的时候被1006和傻逼OJ搞了一波心态就没想出来这个题,赛后发现还是比较简单的...哎...

首先(g(x))肯定没法求导,直接做显然不行。考虑到n的范围最大也就是1e6,六个个位数的和最大就是9 + 9 + 9 + 9 + 9 + 9 = 54,因此g(x)的值域实际上是很小的。这样可以考虑枚举(g(x))的值(a),此时可以发现原函数变成了一个二次函数((g(x))可以看做是定值了),定义域是1到n中所有满足(g(x) = a)(x),要做的就是在这个定义域下求出原函数的最小值。如果开口朝下,就把两个端点值代入更新答案,如果开口朝上则用三分求出来最小值。至于1到54每个(g(x))值对应的(x)可以在一开始的时候就遍历1到1e6预处理出来,push_back进vector数组里,这样也能保证每个vector的数是有序的,满足三分的条件。代码里要注意几处特判。

#include <bits/stdc++.h>
#define int long long
using namespace std;
vector<int> v[100];
int maxx = 0;
void calc(int x) {
	int sum = 0;
	int xx = x;
	while(x) {
		int now = x % 10;
		sum += now;
		x /= 10;
	}
	maxx = max(maxx, sum);
	v[sum].push_back(xx);
}
signed main() {
	int t;
	cin >> t;
	for(int i = 1; i <= 1000000; i++) {
		calc(i);
	}
	while(t--) {
		int a, b, c, d, n;
		cin >> a >> b >> c >> d >> n;
		int A, B;
		int ans = 1e18;
		for(int i = 1; i <= maxx; i++) {
			if(v[i].size()) {
				A = a * i + b;
				B = c * i * i + d * i;
				//Ax^2 + Bx在(v[i][0], min(N, v[i][v[i].size() - 1])) 的最小值
				vector<int>::iterator it = upper_bound(v[i].begin(), v[i].end(), n);
				if(it == v[i].begin()) continue;
				it--;
				int pos = it - v[i].begin();
				if(pos < 0) continue;
				if(A < 0) {
					if(v[i][pos] <= n) ans = min(ans, A * v[i][pos] * v[i][pos] + B * v[i][pos]);
					if(v[i][0] <= n) ans = min(ans, A * v[i][0] * v[i][0] + B * v[i][0]);
				} else if(A == 0) {
					if(B >= 0) {
						if(v[i][0] <= n) ans = min(ans, A * v[i][0] * v[i][0] + B * v[i][0]);
					} else {
						if(v[i][pos] <= n) ans = min(ans, A * v[i][pos] * v[i][pos] + B * v[i][pos]);
					}
				} else {
					int l = 0, r = pos, mid, midmid;
					if(l == r) {//不特判会wa n = 1的情况
						if(v[i][l] <= n) ans = min(ans, A * v[i][l] * v[i][l] + B * v[i][l]);
						continue;
					}
					while(l < r) {
						mid = (2 * l + r) / 3;
						midmid = (2 * r + l + 2) / 3;
						if(A * v[i][mid] * v[i][mid] + B * v[i][mid] < A * v[i][midmid] * v[i][midmid] + B * v[i][midmid]) {
							ans = min(ans, A * v[i][mid] * v[i][mid] + B * v[i][mid]);
							r = midmid - 1;
						} else {
							ans = min(ans, A * v[i][midmid] * v[i][midmid] + B * v[i][midmid]);
							l = mid + 1;
						}
					}
					
				}
			}
		}
		cout << ans << endl;
	}

	return 0;
}
原文地址:https://www.cnblogs.com/lipoicyclic/p/15201308.html