• 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;
    }
    
  • 相关阅读:
    Java SE入门(十三)——高级API
    Java SE入门(十二)——修饰符与内部类
    Java SE入门(十一)——接口与多态
    数据结构与算法(一)——绪论
    break与continue的区别以及终止函数的return false
    文字超出隐藏显示省略号及鼠标放上去显示全部文字信息的写法
    组件有新增修改两种状态该怎么使用
    Math常用的属性和方法
    模块化开发及import用法
    element时间日期选择器组件设置默认时间
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15201308.html
Copyright © 2020-2023  润新知