第1题
输出描述:
一行一个数字表示答案
输入例子1:
5 3
2 11 21
19 10 1
20 11 1
6 15 24
18 27 36
输出例子1:
3
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
map<vector<int>, int> imap; // 列差取-,个数
int res = 0;
for(int i = 0; i < n; i++){
vector<int> a(k); //存一行数字
for(int &t : a) cin >> t;
vector<int> b(k-1); //存列差
for(int j = 1; j < k; j++)
b[j-1] = a[j] - a[j-1];
res += imap[b]; //b逐个元素取-值,然后加1,在此处累加
for(int &t: b) t = -t;
imap[b]++;
}
cout << res << endl;
}
-------------------------------------------------------------------
第2题
输入描述:
对于每一组测试数据, 每行输入个数和。
输出描述:
对于每组输入样例,按字典序输出所有方案选择物品的编号,每种方案占一行
输入例子1:
4 1
输出例子1:
1
2
3
4
输入例子2:
5 2
输出例子2:
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
#include <iostream>
#include <vector>
using namespace std;
void select(vector<int>& nums, vector<int> comb, int begin, int k){
if(k <= 0){
if(k == 0){
for(int i = 0; i < comb.size(); i++){
cout << comb[i] << " ";
}
cout << endl;
}
}
for(int i = begin; i < nums.size(); i++){
comb.push_back(nums[i]);
select(nums, comb, i + 1, k -1);
comb.pop_back();
}
}
int main(){
int n, m;
cin >> n >> m;
if(n < m) return 0;
vector<int> comb;
vector<int> nums(n, 0);
for(int i = 0; i < n; i++)
nums[i] = i + 1;
select(nums, comb, 0, m);
return 0;
}-------------------------------------------------------------------
第三题
题意:n个人过河,一次最多过两人,时间取决于最慢的,求全部渡过河的所用最小时间。
思路:
通过总结分析可得当n为1时,用时a[1],当n为2时,取决于二者最大时间,当n为3时,最小时间为三人用时总和。
当n大于等于4时有两种渡河方案:1、最快和次快先过,最快回,然后当前最慢和当前次慢的过,次快回。
time=a[2]+a[n]+a[1]+a[2].2、始终最快和当前最慢的过河,最快回。在取时间时,要从两者中选最小。
time=a[n]+a[1]+a[n-1]+a[1].
ab ad
----------> ---------->
a a
<---------- <----------
cd ac
----------> ---------->
b a
<---------- <----------
ab ab
----------> ---------->
a + 3b + d 2a + b + c + d
Sample Input
1
4
1 2 5 10
Sample Output
17
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int cross_river(vector<int>& vec, int num)
{
int sum = 0;
if(num == 1) //如果只有一个人
return vec[1];
if(num == 2) // 如果只有两个人
return vec[2];
if(num == 3) //如果有三个人
return vec[1] + vec[2] + vec[3];
for(int j = 2; j <= num; j++)
sum += vec[j];
// 最快的送每一个过河 vec[1] * (num - 2) + sum
// 最快和次快过,最快回, 最慢和次慢过,次快回,递归下去,剩下num-2人
return min(sum + vec[1]*(num-2) , vec[1] + vec[2]*2 + vec[num] + cross_river(vec, num -2));
}
int main(){
int tn, num;
cin >> tn;
while(tn--){
int min = 0;
cin >> num;
vector<int> vec(num + 1);
for(int i = 1 ; i <= num; i++){
cin >> vec[i];
}
sort(vec.begin()+1, vec.begin()+1+num);
min = cross_river(vec, num);
cout << min << endl;
}
return 0;
}
方法二:
迭代改为循环
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int tn, n;
cin >> tn;
while(tn--){
int time = 0;
cin >> n;
vector<int> vec(n + 1);
for(int i = 1 ; i <= n; i++){
cin >> vec[i];
}
sort(vec.begin()+1, vec.begin()+1+n);
while(n > 0){
if(n == 1){
time += vec[1];
break;
}
if(n == 2){
time += vec[2];
break;
}
if(n == 3){
time += vec[1] + vec[2] + vec[3];
break;
}
else{
// 最快和次快过,最快回, 最慢和次慢过,次快回; 最快的送最慢和次慢过河
time = time + min(vec[n] + 2*vec[2] + vec[1], vec[1] * 2 + vec[n] + vec[n-1]);
n = n-2;
}
}
cout << time << endl;
}
return 0;
}
-----------------------------------------------
第4题
小强想要从中选出一个整数,从中选出一个整数 .使得满足 = 的同时且和的乘积最大。如果不存在这样的和,请输出“ 0 0”.
输入描述:
输入一行包含四个整数,,和.
输出描述:
输出两个整数表示满足条件的和.若不存在,则输出"0 0".
输入例子1:
1 1 2 1
输出例子1:
0 0
输入例子2:
1000 500 4 2
输出例子2:
1000 500
输入例子3:
1000 500 3 1
输出例子3:
999 333
#include <iostream>
using namespace std;
int maxG(int a, int b){
int c = 0;
while(b != 0){
c = a % b;
a = b;
b = c;
}
return a;
}
int main(){
int A, B, a, b;
long x, y;
cin >> A >> B >> a >> b;
//求a b最大公约数
int mg = maxG(a, b);
//约分
a = a/mg;
b = b/mg;
//判断x,y是否存在
if( A < a || B < b){
x = 0;
y = 0;
}else{
x = a;
y = b;
while(x + a <= A && y + b <= B){
x += a;
y += b;
}
}
cout << x << " " << y << endl;
}
-----------------------------------------------------------------
第5题
在一张2D地图上小强有n座房子,因为地理位置的原因没有办法给每座房子提供水源,所以小强打算修建一条平行y轴的水渠.因为这条水渠无限长.
所以能够看做是一条平行于y轴的直线. 现在小强想确定修建水渠的位置,能够使得这座房子到水渠的垂直距离和最小,请你输出最小的距离和.
输入描述:
第一行输入一个正整数.
接下来行,每行输入两个正整数,,分别表示每个房子所在的二维坐标.
输出描述:
输出一个整数表示答案
输入例子1:
4
0 0
0 50
50 50
50 0
输出例子1:
100
例子说明1:
当修建水渠位置的直线方程为\mathit x=0或者\mathit x=50时,都能获得最小距离和.
思路:只需取中位数的点便可以得到答案。
例如:
1,9两点,要得到到1,9两点距离之和最小的点,只需取[1,9]内任意一点便可得到最小值。
同理:
若是求到1,3,6,9这四个点距离之和最小的点,
先看[1,9]区间内任意一点到1,9的距离都是最短。
再看[3,6]区间内同样区间内任意一点到3,6的距离都是最小值。
故只需求这两个区间的交集[3,6]内取任意一点便可得到到这四点距离之和的最小值。
因此若n为奇数我们便取这n个点的中位数点。
若n为偶数我们便取这n个点的中间两个点的任意一个(排完序后所得交集区间的端点)
得出所得点l应为(n+1)/2.
注意ans应为long long类型。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int n;
long long sum = 0;
cin >> n;
vector<int> x(n + 1);
vector<int> y(n + 1);
for(int i = 1; i <=n ; i++){
cin >> x[i];
cin >> y[i];
}
sort(x.begin() + 1, x.begin() + 1 + n);
int mid = (1 + n)/2;
for(int j = 1; j <= n; j++){
sum += abs(x[j] - x[mid]);
}
cout << sum << endl;
}
-----------------------------------------------------------------
第6题
国际交流会(圆桌问题)
最近小强主办了一场国际交流会,大家在会上以一个圆桌围坐在一起。由于大会的目的就是让不同国家的人感受一下不同的异域气息,
为了更好地达到这个目的,小强希望最大化邻座两人之间的差异程度和。为此,他找到了你,希望你能给他安排一下座位,
达到邻座之间的差异之和最大。
输入描述:
输入总共两行。
第一行一个正整数,代表参加国际交流会的人数(即圆桌上所坐的总人数,不单独对牛牛进行区分)
第二行包含个正整数,第个正整数a_i代表第个人的特征值。
其中
注意:
邻座的定义为: 第人的邻座为,第人的邻座是,第人的邻座是。
邻座的差异值计算方法为。
每对邻座差异值只计算一次。
输出描述:
输出总共两行。
第一行输出最大的差异值。
第二行输出用空格隔开的个数,为重新排列过的特征值。
(注意:不输出编号)
如果最大差异值情况下有多组解,输出任意一组即可。
输入例子1:
4
3 6 2 9
输出例子1:
20
6 2 9 3
例子说明1:
这么坐的话
差异和为\text |6-2|+|2-9|+|9-3|+|3-6|=20为最大的情况。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
long long sum = 0;
cin >> n;
vector<int> diffnum(n);
vector<int> res;
for(int i = 0; i < n; i++){
cin >> diffnum[i];
}
sort(diffnum.begin(),diffnum.end());
for(int j = 0; j < n/2; j++){
res.push_back(diffnum[j]);
res.push_back(diffnum[n - j -1]);
}
if(n % 2 != 0)
res.push_back(diffnum[n/2]);
for(int k = 1; k < n; k++){
sum += abs(res[k] - res[k-1]);
}
sum += abs(res[n-1] - res[0]);
cout << sum << endl;
for(int ii = 0; ii < n; ii++)
cout << res[ii] << " ";
cout << endl;
}
-------------------------------------------------------------------
第7题
[编程题]小强的神奇矩阵
小强有一个的矩阵,他将中每列的三个数字中取出一个按顺序组成一个长度为的数组,即b_i可以是其中任意一个。问的最小值是多少。
sum |b(i) - b(i+1)| 最小值
输入描述:
第一行,一个正整数。
第二行到第四行输入一个的矩阵,每行输入个正整数。
。
输出描述:
一行一个正整数表示答案。
输入例子1:
5
5 9 5 4 4
4 7 4 10 3
2 10 9 2 3
输出例子1:
5
例子说明1:
数组\mathit b可以为\left[5,7,5,4,4\right],答案为\text 5。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int col;
cin >> col;
vector<vector<int> > input(3, vector<int> (col));
vector<vector<long> > dp(3, vector<long>(col));
long d0, d1, d2;
long min_value;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < col; j++)
{
cin >> input[i][j];
}
}
for(int j = 1; j < col; j++)
{
for(int i = 0; i < 3; i++){
d0 = abs(input[0][j-1] - input[i][j]) + dp[0][j-1];
d1 = abs(input[1][j-1] - input[i][j]) + dp[1][j-1];
d2 = abs(input[2][j-1] - input[i][j]) + dp[2][j-1];
dp[i][j] = min(min(d0,d1),d2);
}
}
min_value = min(min(dp[0][col-1],dp[1][col-1]),dp[2][col-1]);
cout << min_value << endl;
}
-------------------------------------------------------------------
第8题
[编程题]蚂蚁森林之王
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 256M,其他语言512M
很久很久以前,在蚂蚁森林里住着 只小动物,编号从 到 。编号越小的动物能力值越大。现在他们想投票选出一只小动物当森林之王,
对于每只小动物来说,如果他有崇拜的对象,那么他可能投票选择自己,或与自己崇拜的对象投相同票;如果他没有崇拜的对象,那么他投票只可能选择自己。
每只小动物只会崇拜能力值比自己大的小动物。
记者小强拜访了这 只小动物,了解到每只小动物是否有崇拜的对象以及具体是谁。现在他想知道每个人能得到的最高票数是多少。
输入描述:
第一行一个正整数 ,代表小动物的数量。
第二行 个以空格分隔的正整数 ,代表每只小动物崇拜的小动物。
若 ,则代表第 只小动物没有崇拜的对象。
。
保证 。
输出描述:
共 行,第 行代表第 只小动物可能得到的最多票数。
输入例子1:
4
0 1 1 1
输出例子1:
4
1
1
1
例子说明1:
如果第 \text 2,3,4 只小动物均和第一只投一样的票,则第一只小动物可以获得四票。
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> input(n+1);
vector<int> res(n+1, 0);
for(int i = 1; i < n+1; i++){
cin >> input[i];
}
for(int i = n; i > 0; i--){
res[i] += 1;
res[input[i]] = res[input[i]] + res[i];
}
for(int i = 1; i <= n; i++){
cout << res[i] << endl;
}
}
-------------------------------------------------------------
第九题
[编程题]删除字符
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
有一个长度为的字符串 ,你可以删除其中的 个字符,使剩余字符串的字典序最小,输出这个剩余字符串。
输入描述:
第一行输入一个整数,代表接下来有组测试数据。
对于每一组测试数据,第一行输入两个数代表字符串的长度和可以删除的字符数量。
接下来输入长度为字符串。
输出描述:
对于每一组数据,输出一个答案
输入例子1:
2
5 2
abcab
10 4
lkqijxsnny
输出例子1:
aab
ijsnny
ijklnnqsxy
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
void deleteM(string str, int m){
stack<char> stk;
for(int i = 0; i < str.length(); i++){
char cur = str[i];
while(!stk.empty() && stk.top() > cur && m > 0){
stk.pop();
m--;
}
stk.push(cur);
}
//m不为0, 不满足删除个数,继续删除
for(int i = 0; i < m; i++)
stk.pop();
string res;
while(!stk.empty()){
res = stk.top() + res;
stk.pop();
}
cout << res << endl;
}
int main()
{
long len, m, n;
cin >> n;
while(n--){
cin >> len >> m;
string str;
cin >> str;
deleteM(str,m);
}
}
-------------------------------------------------------------------
第10题
小强今天体检,其中有一个环节是测视力
小强看到的视力表是一张的表格,但是由于小强视力太差,他无法看清表格中的符号。
不过热爱数学的他给自己出了这样一个问题:假设现在有a个向上的符号,b个向下的符号,
c个向左的符号,d个向右的符号,把这些符号填到视力表中,总共有多少种可能的情况呢?
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
ll qmi(ll a, ll k, ll p){
int res = 1;
while(k){
if(k & 1) res = res*a % p;
a = a*a%p;
k>>=1;
}
return res;
}
ll C(ll a, ll b, ll p){
if(b > a) return 0;
ll res = 1;
for(ll i = 1, j = a; i <= b; i++, j--){
res = res*j %p;
res = res*qmi(i, p -2, p)%p;
}
return res;
}
ll lucas(ll a, ll b, ll p){
if(a < p && b < p) return C(a, b, p);
return C(a%p, b%p, p) * lucas(a/p,b/p,p)%p;
}
signed main(){
int n, a, b, c, d;
cin >> n >> a >> b >> c >> d;
int p = 998244353;
ll ans = lucas(n * n, n * n - a, p) * lucas(n * n - a, b, p) %p;
ans *= lucas(n * n - a - b, c, p) %p;
cout << ans % p << endl;
}