1、2019南大计算机本科开放日机试题(最小新整数)
给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0。n的位数为m。
现在从m位中删除k位(0<k < m),求生成的新整数最小为多少?
例如: n = 9128456, k = 2, 则生成的新整数最小为12456
输入
第一行t, 表示有t组数据;
接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n, k。
输出
t行,每行一个数字,表示从n中删除k位后得到的最小整数。
样例输入
2
9128456 2
1444 3
样例输出
12456
1
相对位置可以变的情况下:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
int main(void){
string str;
int k, t;
cin >> t;
vector<int> vec[t];
for(int i = 0; i < t; i++){
cin >> str >> k;
for(int j = 0; j < str.size(); j++){
vec[i].push_back(str[j]-48);
}
sort(vec[i].begin(), vec[i].end());
vec[i].erase(vec[i].end()-k, vec[i].end());
}
for(int i = 0; i < t; i++){
copy(vec[i].begin(), vec[i].end(), ostream_iterator<int>(cout, ""));
cout << endl;
}
return 0;
}
相对位置不可以改变:
/**
* 思路:最长上升子序列的变种
* 每遍历到字符串中的字符,若存在比当前字符大的字符,则删除之
* 直到删除的个数已为k 或遍历到了 最后一个字符为止
*
*/
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
string num;
int k;
cin >> num >> k;
if(k == 0) {
cout << num;
return 0;
}
int len = num.length();
int finalLen = len - k;
if(finalLen <= 0) {
cout << "";
return 0;
}
int flag[len];
memset(flag,0,sizeof(flag));
int i = 1;
int j = 0;
// 有可能存在 12345 这种删除字符数目不够k 的情况
// 则将前 len - k 个 字符打印之
while(i < len && k > 0) {
int a = num[i] - '0';
for(int j = 0;j < i;j++) {
int b = num[j] - '0';
if(a < b && flag[j] == 0) {
flag[j] = 1;
k--;
if(k == 0) {
break;
}
}
}
i++;
}
for(int i = 0;i < len;i++) {
if(flag[i] == 0 && finalLen > 0) {
cout << num[i];
finalLen--;
}
}
return 0;
}
2、暨南大学-计算机机试(合并果子问题)
其实,就是一道经典的哈夫曼问题,大致解法:
#include <cstdio>
#include <queue>
using namespace std;
//代表小顶堆的优先队列
priority_queue<long long, vector<long long>, greater<long long> > q;
int main(void){
int n; //n堆果子
long long temp, x, y, ans = 0;
scanf("%d", &n);
for(int i = 0; i < ans; i++){
scanf("%lld", &temp); //将初始重量压入优先队列
q.push(temp);
}
while(q.size() > 1){ //只要优先队列中至少有两个元素
x = q.top();
q.pop();
y = q.top();
q.pop();
q.push(x+y); //取出堆顶的两个元素,求和后压入优先队列
ans += x+y; //累计求和的结果
}
printf("%lld\n", ans); //ans即为消耗的最小体力
return 0;
}
hyy做法:容器中当前元素的下一个元素的值加上当前元素,最后减去容器中第一个元素即为最小带权路径
#include<iostream>
#include<vector>
#include<functional>
#include <numeric>
#include<algorithm>
using namespace std;
int main(){
int n,x,a[1000],b[1000],sum=0;
cin>>n;
int m = n;
while(m--){
cin>>x;
a[m]=x;
}
vector<int> v(a,a+n);
sort(v.begin(),v.end());
vector<int>::iterator i=v.begin();
//vector<int>::iterator i1=v.begin();
//cout << "=====" << endl;
for(;i!=v.end()-1;i++)
*(i+1)+=*(i);
sum = accumulate(v.begin(), v.end(), 0);
//cout << "sum : " << sum << endl;
cout<<sum-*v.begin() << endl;
return 0;
}
3、求解100以内的素数
解法一:正常存储素数表
#include <cstdio>
#include <cmath>
bool isPrime(int n){ //判断n是否是素数
if(n <= 1)
return false;
int sqr = (int)sqrt(1.0*n);
for(int i = 2; i <= sqr; i++){
if(n % i == 0)
return false;
}
return true;
}
int prime[101], num = 0; //素数的个数
void findPrime(){ //求素数表
for(int i = 1; i < 101; i++){
if(isPrime(i) == true){
prime[num++] = i;
p[i] = true;
}
}
}
int main(void){
findPrime();
for(int i = 0; i < num; i++){
printf("%d", prime[i]);
if(i < num-1){
printf(" ");
}
}
return 0;
}
解法二:埃式筛法
#include <cstdio>
const int maxn = 101;
int prime[maxn], num = 0; //素数的个数
bool p[maxn] = {0}; //记录当前下标代表的值是否是素数
void findPrime(){
for(int i = 2; i < maxn; i++){
if(p[i] == false){
prime[num++] = i;
//筛去i~100之间所有i的倍数
for(int j = i + i; j < maxn; j += i){
p[j] = true;
}
}
}
}
int main(void){
findPrime();
for(int i = 0; i < num; i++){
printf("%d", prime[i]);
if(i < num-1){
printf(" ");
}
}
return 0;
}