前些年优快云上有英雄会编程比赛,其中2014年平安科技在线编程大赛,部分题目如下。附上本人的分析和答案。
1. 火车调度
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=584&&ExamID=579
问题分析:
这道题目,官方给出了4星(较难)的难度等级,过分了……
对输入的时刻建立4个链表,分别是:A站出发时刻表、A站到达时刻表、B站出发时刻表、B站到达时刻表。AB站的最小车库存量初始设为AB站各自出发的车列数(即各自站点的出发时刻表的size)。遍历出发列表,对比到达列表,出发前有前序到达,且满足检修时间的,则初始库存数减一。如此,问题得解。
解答:
#include <iostream>
#include <list>
using namespace std;
void fun(unsigned int t, list <unsigned int> a_leave, list <unsigned int> b_arrive,
list <unsigned int> b_leave, list <unsigned int> a_arrive,
unsigned int &an, unsigned int &bn)
{
an = a_leave.size();
bn = b_leave.size();
a_leave.sort();
b_arrive.sort();
b_leave.sort();
a_arrive.sort();
list <unsigned int>::iterator it1 = a_leave.begin();
list <unsigned int>::iterator it2 = a_arrive.begin();
while (it1 != a_leave.end())
{
if (it2 == a_arrive.end())
break;
if (*it1 >= *it2 + t)
{
--an;
++it1;
++it2;
}
else
{
++it1;
}
}
it1 = b_leave.begin();
it2 = b_arrive.begin();
while (it1 != b_leave.end())
{
if (it2 == b_arrive.end())
break;
if (*it1 >= *it2 + t)
{
--bn;
++it1;
++it2;
}
else
{
++it1;
}
}
}
int main()
{
unsigned int t, na, nb;
unsigned int hour1, min1, hour2, min2;
unsigned int an, bn;
char c;
list <unsigned int> a_leave, b_arrive, a_arrive, b_leave;
while (cin >> t)
{
if (cin >> na >> nb)
{
for (unsigned int i = 0; i < na; i++)
{
scanf_s("%2d:%2d %2d:%2d", &hour1, &min1, &hour2, &min2);
a_leave.push_back(hour1 * 60 + min1);
b_arrive.push_back(hour2 * 60 + min2);
}
for (unsigned int i = 0; i < nb; i++)
{
scanf_s("%2d:%2d %2d:%2d", &hour1, &min1, &hour2, &min2);
b_leave.push_back(hour1 * 60 + min1);
a_arrive.push_back(hour2 * 60 + min2);
}
fun(t, a_leave, b_arrive, b_leave, a_arrive, an, bn);
cout << an << " " << bn << endl;
a_leave.clear();
b_arrive.clear();
b_leave.clear();
a_arrive.clear();
}
}
return 0;
}
2. 另类编辑距离
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=580&&ExamID=575
问题分析:
显然,这是一道求最大公共子序列的题目。将两个字符串与公共子串的差相加,即为结果。
解答:
#include <iostream>
#include <string>
using namespace std;
int fun(string str1, string str2)
{
int row = str1.length()+1;
int column = str2.length()+1;
int value;
int ** martix = new int * [row];
for (int i = 0; i < row; i++)
{
martix[i] = new int [column];
}
for (int i = 0; i < row; i++)
{
martix[i][0] = 0;
}
for (int j = 0; j < column; j++)
{
martix[0][j] = 0;
}
for (int i = 1; i < row; i++)
{
for (int j = 1; j < column; j++)
{
if (str1[i - 1] == str2[j - 1])
{
martix[i][j] = martix[i - 1][j - 1] + 1;
}
else
{
martix[i][j] = martix[i - 1][j] > martix[i][j - 1] ?
martix[i - 1][j] : martix[i][j - 1];
}
}
}
value = row + column - 2 - 2 * martix[row - 1][column - 1];
for (int i = 0; i < row; i++)
{
delete [] martix[i];
}
delete [] martix;
return value;
}
int main()
{
string str1, str2;
while (cin >> str1 >> str2)
cout << fun(str1, str2) << endl;
return 0;
}
int row = str1.length()+1;
int column = str2.length()+1;
int value;
int ** martix = new int * [row];
for (int i = 0; i < row; i++)
{
martix[i] = new int [column];
}
for (int i = 0; i < row; i++)
{
martix[i][0] = 0;
}
for (int j = 0; j < column; j++)
{
martix[0][j] = 0;
}
for (int i = 1; i < row; i++)
{
for (int j = 1; j < column; j++)
{
if (str1[i - 1] == str2[j - 1])
{
martix[i][j] = martix[i - 1][j - 1] + 1;
}
else
{
martix[i][j] = martix[i - 1][j] > martix[i][j - 1] ?
martix[i - 1][j] : martix[i][j - 1];
}
}
}
value = row + column - 2 - 2 * martix[row - 1][column - 1];
for (int i = 0; i < row; i++)
{
delete [] martix[i];
}
delete [] martix;
return value;
}
int main()
{
string str1, str2;
while (cin >> str1 >> str2)
cout << fun(str1, str2) << endl;
return 0;
}
3. 最小公倍数
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=600&&ExamID=595
问题分析:
分解m的质因数,全部属于给定数列,即为Possible。
解答:
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
struct myStruct
{
long factor;
int exponent;
};
bool fun(long * array, long n, long m)
{
if (n <= 0 || m <= 0)
return false;
vector <myStruct> primes;
// 本不想用temp变量,但在线编译器不支持myStruct{i, exponent}的格式
myStruct temp;
if (m == 1)
{
temp.factor = 1;
temp.exponent = 1;
primes.push_back(temp);
}
else
{
long key = (long)sqrt((double)m);
long i, mp;
for (i = 2, mp = m; i <= key; i++)
{
int exponent = 0;
while (mp % i == 0)
{
exponent++;
mp /= i;
}
if (exponent > 0)
{
temp.factor = i;
temp.exponent = exponent;
primes.push_back(temp);
}
}
if (mp > key)
{
temp.factor = mp;
temp.exponent = 1;
primes.push_back(temp);
}
}
for (long i = 0; i < n; i++)
{
if (m % array[i] != 0)
continue;
vector <myStruct> ::iterator it = primes.begin();
while (it != primes.end())
{
if (array[i] % (long)pow((double)(it->factor), it->exponent) == 0)
it = primes.erase(it);
else
++it;
}
if (primes.empty())
break;
}
if (primes.empty())
return true;
else
{
primes.clear();
return false;
}
}
int main()
{
long n, m;
long * array;
while (cin >> n >> m)
{
array = new long[n];
for (long i = 0; i < n; i++)
{
cin >> array[i];
}
if (fun(array, n, m))
cout << "Possible" << endl;
else
cout << "Impossible" << endl;
delete[] array;
}
return 0;
}
long factor;
int exponent;
};
bool fun(long * array, long n, long m)
{
if (n <= 0 || m <= 0)
return false;
vector <myStruct> primes;
// 本不想用temp变量,但在线编译器不支持myStruct{i, exponent}的格式
myStruct temp;
if (m == 1)
{
temp.factor = 1;
temp.exponent = 1;
primes.push_back(temp);
}
else
{
long key = (long)sqrt((double)m);
long i, mp;
for (i = 2, mp = m; i <= key; i++)
{
int exponent = 0;
while (mp % i == 0)
{
exponent++;
mp /= i;
}
if (exponent > 0)
{
temp.factor = i;
temp.exponent = exponent;
primes.push_back(temp);
}
}
if (mp > key)
{
temp.factor = mp;
temp.exponent = 1;
primes.push_back(temp);
}
}
for (long i = 0; i < n; i++)
{
if (m % array[i] != 0)
continue;
vector <myStruct> ::iterator it = primes.begin();
while (it != primes.end())
{
if (array[i] % (long)pow((double)(it->factor), it->exponent) == 0)
it = primes.erase(it);
else
++it;
}
if (primes.empty())
break;
}
if (primes.empty())
return true;
else
{
primes.clear();
return false;
}
}
int main()
{
long n, m;
long * array;
while (cin >> n >> m)
{
array = new long[n];
for (long i = 0; i < n; i++)
{
cin >> array[i];
}
if (fun(array, n, m))
cout << "Possible" << endl;
else
cout << "Impossible" << endl;
delete[] array;
}
return 0;
}
4. F(X)
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=519&&ExamID=514
问题分析:
读懂题目,此题就不难了。
将n分解质因数,再将质因数组合为2组即可。
对于合数,其相同的k个质因数,不完全分成2有序组的方法共(k+1)(k+2)/2种,所有质因数的分法相简乘,为解。
对于质数,显然F(x)==3。
解答:
#include <iostream>
#include <cmath>
using namespace std;
long long fun(long long n)
{
if (n <= 0)
return 0;
if (n == 1)
return 1;
long long number;
long long all = 1;
long long threshold = (long long)ceil(sqrt((double)n));
for (long long i = 2; i <= threshold; i++)
{
number = 0;
while (n % i == 0)
{
number++;
n /= i;
}
if (number > 0)
all *= (number + 1)*(number + 2) / 2;
if (i > n)
break;
}
if (n > 1)
all *= 3;
return all;
}
int main()
{
long long n;
while (cin >> n)
{
cout << fun(n) << endl;
}
return 0;
}
if (n <= 0)
return 0;
if (n == 1)
return 1;
long long number;
long long all = 1;
long long threshold = (long long)ceil(sqrt((double)n));
for (long long i = 2; i <= threshold; i++)
{
number = 0;
while (n % i == 0)
{
number++;
n /= i;
}
if (number > 0)
all *= (number + 1)*(number + 2) / 2;
if (i > n)
break;
}
if (n > 1)
all *= 3;
return all;
}
int main()
{
long long n;
while (cin >> n)
{
cout << fun(n) << endl;
}
return 0;
}
5. -3+1
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=503&&ExamID=498
问题分析:
这个题目让我想起拼烟头问题。
将全部数字除以3取余数,商即为需要+1的个数。然后把这些+1分别安插在数字中。
余数为0的,忽略;余数为2的,+1后可再次-3变为0,操作数+1;余数为1的,两次+1后可再次-3变为0;最后加上剩余的+1可完成的操作数。
解答:
#include <iostream>
using namespace std;
unsigned long long fun(unsigned long * array, unsigned int n)
{
unsigned long long var = 0ul;
unsigned long long all = 0ul;
for (unsigned int i = 0; i < n; i++)
{
var += array[i] / 3;
array[i] %= 3;
}
if (var == 0)
return 0;
all = var;
for (unsigned int i = 0; i < n; i++)
{
if (array[i] == 2)
{
if (var > 1)
all++;
}
else if (array[i] == 1)
{
if (var > 1)
{
var--;
all++;
}
}
}
all += (var+1)/2-1;
return all;
}
int main()
{
unsigned int n;
unsigned long * array;
while (cin >> n)
{
array = new unsigned long [n];
for (unsigned int i = 0; i < n; i++)
{
cin >> array[i];
}
cout << fun(array, n) << endl;
delete[] array;
}
return 0;
}
unsigned long long var = 0ul;
unsigned long long all = 0ul;
for (unsigned int i = 0; i < n; i++)
{
var += array[i] / 3;
array[i] %= 3;
}
if (var == 0)
return 0;
all = var;
for (unsigned int i = 0; i < n; i++)
{
if (array[i] == 2)
{
if (var > 1)
all++;
}
else if (array[i] == 1)
{
if (var > 1)
{
var--;
all++;
}
}
}
all += (var+1)/2-1;
return all;
}
int main()
{
unsigned int n;
unsigned long * array;
while (cin >> n)
{
array = new unsigned long [n];
for (unsigned int i = 0; i < n; i++)
{
cin >> array[i];
}
cout << fun(array, n) << endl;
delete[] array;
}
return 0;
}
6. An easy problem
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=500&&ExamID=495
问题分析:
先把题目的数学语言翻译成人话:
对于给定的非负整数n和m,求正整数c满足:
(1)对任两个非负整数x和y, 必存在一个极小正实数ε0,使得 |n*x+m*y-c|>ε0.
(2)对任一非负整数d,且d>c,必存在两个非负整数x'和y',使得对任一极小正实数ε,均有|n*x'+m*y'-d|<ε.
其中,n和m的最大公约数为1,以上整数均在64位二进制数以内。
再好理解一点:
对于给定的非负整数n和m,求正整数c满足:
(1)无论多少个n和m,都累加不出c来.
(2)所有比c大的数,都能用n和m累加出来
其中,n和m的最大公约数为1,以上整数均在64位二进制数以内。
两个互质数,通过不限次数的加减计算,可以得出所有整数
解答:
#include <iostream>
using namespace std;
long long fun(long long n, long long m)
{
if (n <= 1 || m <= 1)
return 0;
return n*m-n-m;
}
int main()
{
long long n, m;
long long c;
while (cin >> n >> m)
{
c = fun(n, m);
if (c > 0)
{
cout << c << endl;
}
else
{
cout << "impossible." << endl;
}
}
return 0;
}
if (n <= 1 || m <= 1)
return 0;
return n*m-n-m;
}
int main()
{
long long n, m;
long long c;
while (cin >> n >> m)
{
c = fun(n, m);
if (c > 0)
{
cout << c << endl;
}
else
{
cout << "impossible." << endl;
}
}
return 0;
}
7. 第五届在线编程大赛月赛第三题:石子游戏(1)
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=617&&ExamID=612
问题分析:
1.所有数以二进制按位异或求和
2.对于异或和为0的数组,无论下一手如何取,
结果都使异或和不为0,或不能取(失败)
3.对于异或和不为0的数组,一定存取某取法,
使得异或和变为0。如下:
对于非0的32位无符号整数A,其填位补码
B = -(0xFFFFFFFF | A),
如果数组中最大数==A,则此数减去A后,异或和重置为0;
如果数组中最大数!=A,则此数减去B后,异或和重置为0
4.结论:异或和非0必胜,否则必败
解答:
#include <iostream>
#include <cmath>
using namespace std;
bool win(unsigned long * var, unsigned int n)
{
unsigned long a = 0ul;
for (unsigned int i = 0; i < n; i++)
{
a ^= var[i];
}
if (a == 0ul)
return false;
else
return true;
}
int main()
{
unsigned int n;
while (cin >> n)
{
unsigned long * stones = new unsigned long [n];
for (unsigned int i = 0; i < n; i++)
{
cin >> stones[i];
}
if (win(stones, n))
cout << "Win" << endl;
else
cout << "Lost" << endl;
delete[] stones;
}
return 0;
}
unsigned long a = 0ul;
for (unsigned int i = 0; i < n; i++)
{
a ^= var[i];
}
if (a == 0ul)
return false;
else
return true;
}
int main()
{
unsigned int n;
while (cin >> n)
{
unsigned long * stones = new unsigned long [n];
for (unsigned int i = 0; i < n; i++)
{
cin >> stones[i];
}
if (win(stones, n))
cout << "Win" << endl;
else
cout << "Lost" << endl;
delete[] stones;
}
return 0;
}
8. 第五届在线编程大赛月赛第一题:完全平方数的个数
问题描述:
http://hero.youkuaiyun.com/Question/Details?ID=608&&ExamID=603
问题分析:
这道题目是给初中生玩的吧?a和b开平方,取中间整数个数,结束。
解答:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a, b;
int n;
//输入数据
while (cin >> a >> b)
{
float a1 = sqrt((float)a);
float b1 = sqrt((float)b);
a = (int) ceil(a1);
b = (int) floor(b1);
n = b >= a ? b-a+1 : 0;
cout << n << endl;
}
return 0;
}
全部内容原创,转载请注明出处!