黑龙江农垦科技职业学院喜迎寒假多校联赛2

数组截取
链接:https://ac.nowcoder.com/acm/contest/11471/A
来源:牛客网

题目描述
有一段数组n 从中截取和为k的一部分 最长可以截取多长?(如果截取不到正好为k的情况下输出-1)
注意:
出题人:出个数组截取吧;验题人:数据太弱了加强一下;出题人:陷入沉思,OK

本题因为验题人吐槽,数据太弱所以加强了一点点,一点点…
因为数据比较多 请使用你认为最快的读取方式 最省内存的运算方法。反正C++标程 500ms 256mb 内跑过去了。
输入描述:
第一行输入两个整数 n,k
1<n<=2×107
0<=k<=1018
第二行输入n个正整数(包含0)
a1 a2 …an (0<=ai<=1012) 1<=i<=n
输出描述:
输出运算结果
示例1
输入
复制
10 3
3 3 1 1 1 0 0 0 3 3
输出
复制
6
示例2
输入
复制
10 3
6 6 6 6 6 6 6 6 6 3
输出
复制
1
备注:
注意数据及其多 请使用快速的读取方式
以及内存很小 不要浪费 哦

很典型的双指针类型的题,但是数据范围有些大,凡是涉及区间求和得问题都可以用前缀和优化

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int  long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#define x first
//#define y second

//int dx[4] = {0, 1, 0, -1};
//int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 2e7 + 10;
const int M = 2e7 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, k;
int a[N];

signed main(){
	scanf("%lld%lld", &n, &k);
	
	for (int i = 1; i <= n; i ++){
		gt(a[i]);
	}
    
	int ans = -1;
	int temp = 0;
	for (int i = 1, j = 1; i <= n; i ++){
		while(temp <= k && j <= n){
			temp += a[j];
			j ++;
		}
	//	cout << temp << "     " << j << endl;
		if (temp - a[j - 1] == k && j <= n)    ans = max(ans, j - i - 1);
		else  if (temp == k && j > n)    ans = max(ans, j - i);
		temp -= a[i];
	}
	

	cout << ans << endl;
	
	return 0;
}

群友们在排列数字
链接:https://ac.nowcoder.com/acm/contest/11471/B
来源:牛客网

题目描述
群友们在玩一个游戏,共n个人在玩 每个人要在0-(n-1)中选一个数,注意每个数只能选择一次,
然后按照先后选择顺序拼成一个数,计算组成的数字是否可以整除k,
群友们想知道,如果选择方案不重复,最多有多少种情况可以整除k?
如果不可能整除k请输出-1;
输入描述:
第一行输入两个正整数 n,k
1<=n<=10,1<=k<=107

输出描述:
输出结果
示例1
输入
复制
2 1
输出
复制
2
说明
01 10 两种组合除以1都可以除开

很典型的dfs的题,先爆搜出来所有的排列组合,然后看这种排列组合的数是多少,并且看这个数能否整除k
我们需要设置两个参数,第一个是当前搜得了几个数,另外一个是当前搜得的数的组合是什么

void DFS(int x,int now) {
    for(int i = 0 ; i < n ; i ++) {
        if(book[i] == 0) {
            book[i] = 1;
            int Q = now;
            now = now * 10 + i;
            if(x == n) total+= ((now % k) == 0);
            else DFS(x + 1,now);
            now = Q;
            book[i] = 0;
        }
    }
    return ;
}

issue与lifehappy给学生分组
链接:https://ac.nowcoder.com/acm/contest/11471/D
来源:牛客网

issue与lifehappy在给学生分组 现在他们手里有一组n分学生量化好的数据a 这份数据是一个数字,代表学生的大致实力
他们要给学生分成m组并且要求总实力和的最大值最小(ccpc抢名额战略,分散一点)
不过学生们已经拉帮结派的排好队了 所以 issue与lifehappy只能选取这组数据中的连续队列。
输入描述:
第一行 n m n个学生 分成m组
1<=m<=n<=106
第二行为n正整数an
a1 a2 …an (0<=ai<=1011) 1<=i<=n(保证最终结果在ull内)
输出描述:
输出分组后总实力最大值的最小
示例1
输入
复制
5 3
1 8 9 4 2
输出
复制
9

凡是涉及最大值,最小值,最大值的最小值都要想一想二分出答案

一定要注意最后那一组还有一组!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#define x first
//#define y second

//int dx[4] = {0, 1, 0, -1};
//int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 2e6 + 10;
const int M = 2e7 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m;
int a[N];
int s[N];

bool check(int mid){
	for (int i = 1; i <= n; i ++){
		if (a[i] > mid)   return false;
	}
	
	int last = 0, cnt = 0;
	
	for (int i = 1; i <= n; i ++){
		if (s[i] - s[last] > mid){
			cnt ++;
			last = i - 1;
			if (cnt >= m)   return false;
		}
	}
	return true;
}

signed main(){
	scanf("%lld%lld", &n, &m);
	
    int maxd = 0;
	for (int i = 1; i <= n ; i ++)   scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i ++)   maxd = max(maxd, a[i]);
	for (int i = 1; i <= n; i ++)   s[i] = s[i - 1] + a[i];
	
	int l = maxd, r = 1e18;
	
	while(l < r){
		int mid = (l + r) / 2;
		//cout << mid << "-----" << endl;
 		if (check(mid))   r = mid;
		else l = mid + 1;
	}
	
	cout << l << endl;
	
	return 0;
}

删删删越小越好
链接:https://ac.nowcoder.com/acm/contest/11471/E
来源:牛客网

题目描述
这一天Kadia与Majiagou在教学弟,
突然提出了一个问题 给你一个超大的数字 让你从中删掉几位 怎么让他最小?
这种签到题不会还有人写不出来吧 不会吧不会吧
输入描述:
第一行输入一个整数N
1<=len(N)<=2×107
第二行输入一个整数k代表删除几个数字
0<=k<=len(N)
输出描述:
输出结果
示例1
输入
复制
10000
1
输出
复制
0
说明
删掉1结果为0
示例2
输入
复制
12347897187194164979
10
输出
复制
1114164979

前面的数字越小越好,先找到保留最后的数字后,剩下的数字最小的往前放,大的堆在后面,如果有更小的,保证还剩下最少的个数并且前面有任的情况下,一直往前面放,很明显了,这是一道堆栈的题,模拟即可,记得去掉前导0

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int  long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#define x first
//#define y second

//int dx[4] = {0, 1, 0, -1};
//int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 2e7 + 10;
const int M = 2e7 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

char a[N];
int top;

signed main(){
    ios;
		string s;
		int n;
		cin >> s >> n;
		int len = s.size() - n;
		if (len == 0){
			cout << "0" << endl;
			return 0;
		}	
		
		top = 0;
		for (int i = 0; i < s.size(); i ++){
			while(top && a[top - 1] > s[i] && n){
				n --;
				top --;
			}
			a[top ++] = s[i];
		}
		
		int idx = 0;
		while(idx < len && a[idx] == '0'){
			idx ++;
		}
		
		if (idx == len){
			cout << "0" << endl;
			return 0;
		}
		else{
			for (int i = idx; i < len; i ++)
			cout << a[i];
		}

	return 0;
}

happy的异或运算
链接:https://ac.nowcoder.com/acm/contest/11471/F
来源:牛客网

题目描述
我们都知道有一种位运算叫做异或,那么这道题是一道思维题。
给出一个整数n,请求出1-n之间选取两个数进行异或最大能得出多大?(两个数可以相同)
输入描述:
1 ≤ N ≤1018
输出描述:

示例1
输入
复制
10000
输出
复制
16383
示例2
输入
复制
648
输出
复制
1023
示例3
输入
复制
324
输出
复制
511

最大的肯定是都是1的情况多少位都是啥即可

Alan%%%
链接:https://ac.nowcoder.com/acm/contest/11471/G
来源:牛客网

题目描述
又是欢快的一天,牛客多校算法训练营4又在日常%Alan。qcjj想知道到底Alan被%了多少次,所以整理了一下聊天记录。
如果一句话中存在Alan,那么那句话中的%都算%了Alan。由于可能话中有空格,所以去掉空格后形成的Alan也算Alan。
输入描述:
第一行输入整数n表示聊天记录行数
1<=n<=1000
以下n行每行一个字符串s代表聊天记录
1<=s.length<=1000
输出描述:
输出%Alan次数
示例1
输入
复制
5
%alan%%
%Alan%%%
cdqwsq%% A l a n%%
%AC lan%%
%Alan%%%
输出
复制
12

读入一整行,用getlin,然后枚举把空格删了,最后看有多少%,再看是否有ALEN即可

   int tail = 0;
    getline(cin,a);
    int len = a.length();
    for(int i = 0 ; i < len ; i ++)
    if(a[i] != ' ' && a[i] != '\n') tail ++ , S[tail] = a[i];
    int cnt = 0,flag = 0;
    for(int i = 1 ; i <= tail ; i ++) {
       if(S[i] == '%') cnt ++;
       if(S[i] == 'A' && S[i + 1] == 'l' && S[i + 2] == 'a' && S[i + 3] == 'n') flag = 1;
    }
    Ans += cnt * flag;
    for(int i = 1 ; i <= tail ; i ++) S[i] = '\0';
    return ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值