zoukankan      html  css  js  c++  java
  • #周测 9 —— 高低位交换、Subsequences Summing to Sevens S、积木大赛、跳石头


    很简单的一次周测,先简略记录一下。

    周测网站(给在该团队的人看的)

    高低位交换

    #include<bits/stdc++.h>
    using namespace std;
    int s[33];
    int main(){
    	long long x;
    	cin >> x;
    	for(int i = 32; i >= 1; i --){
    		//如果当前最低位上有数 
    		if(x % 2 == 1) s[i] = 1;//对应位置为 1
    		x >>= 1;//处理完之后就去掉最后一位 
    	}
    	
    	for(int i = 17; i <= 32; i ++){
    		x <<= 1;
    		x |= s[i];
    	} 
    	for(int i = 1; i <= 16; i ++){
    		x <<= 1;
    		x |= s[i];
    	} 
    	cout << x;
    	return 0;
    }
    /*
    //首先来分析一下,这道题很有意思;
    //给定一个数 x,  
    //然后 按照二进制码, 将它 的前十六位 与 后十六位 交换;
    //具体操作:
    //一、用另一个数 a 来 复制这个数 x;
    //二、将 a往后移16位:
    	//a >> 16;
    //三、同样的, 用一个数 b 来复制 x , 并将其 往前移16位;
    //最后将 a、b相加; 
    //不出意料失败了;
    //不过没关系,我们分开来做
    //首先最最重要的就是后十六位, 因为我们不知道往前移会发生什么东西;
    //所以我们先将这个数的二进制位拆分:
    	for(int i = 1; i <= 32; i ++){
    		//如果当前最低位上有数 
    		if(x % 2) s[i] = 1;//对应位置为 1
    		x >> 1;//处理完之后就去掉最后一位 
    	} 
    //现在我们处理完了,下一步就是重新组合这个数了
    //第一步,我们将第17到32位的数加上,也就是先把 y 往右移一位,然后 |1(或上1) 
    //第二步,我们将第1到16位上的数进行操作 ~ 完成 ~ 
    //后来发现 x 取完之后就空了,于是计划好的 y 就变成 x 了;
    //为了防止某些 边界问题 我保险起见用long long 吧 
    */
    

    跳石头

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e6 + 10;
    ll a[N];
    int main(){	
    	ll L;
    	int n, m; 
    //	scanf("%d%d%d", &L, &n, &m);//最大距离, 石头数, 最大移走数 
    	cin >> L >> n >> m;
    	for(int i = 1; i <= n; i ++){
    		ll d;
    //		scanf("%d", &d);
    		cin >> d;
    		a[i] = d;
    	}
    	if(n == 0){
    		cout << L;
    		return 0;
    	}
    	//二分答案:使得选手们在比赛过程中的最短跳跃距离尽可能长 我们就枚举 这个——最短的跳跃距离。 
    	ll l = 0, r = L + 1, mid;
    	int k = 1;
    	//现在第一块没有被移走的石头就是1了 
    	//k代表的是	 还未被移走的第一块 石头, 于是我们每移走一块石头,k都要向后移一位。 
    	int cnt;
    	a[n + 1] = L;
    	ll res = -1;
    	while(l <= r){
    		cnt = 0, k = 1;//每一轮都要刷新一次哦。 
    		mid = (l + r) / 2;
    		for(int i = 0; i <= n;){//为什么从第0块石头开始枚举呢?因为第0块石头就是起点 
    			
    			ll d = a[k] - a[i]; //d是当前节点到 k 的距离啦	
    			while(mid > d && k <= n){//如果 d 小于我们要求的最小距离,那么就把 第k块石头 移开  
    				cnt ++;//移开的数目++ 
    				k ++;//k往后移 
    				d = a[k] - a[i]; //更新 d 的值 
    			}	
    			//现在这一轮之后,从i开始后面符合距离的石头全部移开了,那么下一步我们就要跳到 k这个位置上了
    			i = k;
    			k ++;
    		}
    		if(cnt <= m){//合法 ,增加距离 
    			res = max(res, mid);
    			l = mid + 1;
    		} 
    		else {//不合法 ,缩短距离 
    			r = mid - 1;
    		}
    	}	
    	cout << res<< endl;
    //	printf("%lf MB", (double)sizeof(a) / (1024 * 1024));
    	return 0;
    }
    //什么意思呢?就是说,移走之后, 所有石头之间的距离大于等于这个数 。
    //那哪些石头会被移走呢? 
    //从第i块石头到第j块石头的距离 d 如果 小于 我们所枚举的这个距离 mid,那就移走第j块石头;
    //那移走会怎么样? cnt ++ 
    //不移走呢?那就把指针 k 移动到第j块石头上 
    //如果 结果 比 能移开的石头数多, 那我们尝试缩小这个距离;注意:这是不合法的,所以它的答案我们一律不会采纳。 
    //如果 结果 比 能移开的石头数少, 那就扩大这个距离;注意:此时它的答案是合法的,所以我们会采纳尽量大的数; 
     //如果没有石头可以移动呢???!!! 
    

    积木大赛

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    typedef long long ll;
    int a[N], tail;//从1开始 , 所以尾巴在0这里,代表没有数! 
    //优先队列 
    ll cnt;
    int main(){
    	int n, x;
    	cin >> n;
    	for(int i = 1; i <= n; i ++){
    		scanf("%d", &x);//当前的数,但不急着加入 
    		
    		//先判断它与最后一个元素的关系
    		//首先是大于等于最后一个元素 
    			//那就直接加入就好 
    		if(x >= a[tail]){ a[++tail] = x; } 
    		
    		//然后是小于最后一个元素 
    		else{
    			//首先将操作数加上
    			cnt += (ll)(a[tail] - x);
    			//然后将所有前面比他高的全部干掉吧 !(嫉妒心:MAX ) 
    			//移动尾巴就好啦,不用枚举;注意不用超出数组范围 
    			while(tail > 0 && a[tail] > x) tail --;
    			//然后就可以入队啦 
    			a[++tail] = x;
    		}
    	}
    	//最后的处理 
    	cnt += (ll)a[tail]; 
    	cout << cnt;
    	return 0;
    }
    /*
    //好形象啊
    //似乎可以用优先队列来做
    //不过又有所不同,毕竟它是每次只能建一层楼高…… 
    //对了!!!如果本次输入导致那一层的延续断掉了,那么cnt++不久好了吗?
    
    //分两种情况,
    //第一种: 这次输入的是比优先队列最后一个元素大的
    //直接加入吧没什么大不了的 
    //第二种: 这次输入的是比优先队列最后一个元素小的 
    //这就有意思了,我们要将 最后一个元素 到 当前元素中间的所有楼层都 “建好”。
    //也就是操作数为 两者之差;
    cnt += (a[tail] - x);
    //第三种,最后的处理;
    //最后剩下的怎么办??
    //最简单了,直接加上最后一个元素就可以了!!!
    cnt += a[tail]; 
    //cnt会超出int 的范围吗??
    //cnt最大会是多少呢??
    //假设有一个很邪恶的数据,它每次都卡范围,按照10000、1、10000、1……的顺序来建房子
    //这样的组合最多有50000个,每一组侧次数是9999(算它10000)
    //那么我们的cnt最大就是 500000000 , 9位数啦!!!
    //所以以防万一,我们开long long ! 
    */
    

    Subsequences Summing to Sevens S

    //Subsequences Summing to Sevens S
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    int a[N], s[N], b[7];
    //b是那个数第一次出现在的位置 
    int res = -1;
    int main(){
    	memset(b, -1, sizeof b);
    	int n;
    	cin >> n;
    	for(int i = 1; i <= n; i ++){
    		scanf("%d", &a[i]);
    		a[i] %= 7;
    		s[i] = (a[i] + s[i - 1]) % 7;
    		if(b[a[i]] == -1) b[a[i]] = i;//没有出现过就更新位置 
    	}
    	//前缀和 %7
    	
    	for(int i = 1; i <= n; i ++)
    		if(s[i] == 0) res = max(res, i);
    		else if(b[s[i]] != -1 && b[s[i]] < i)//如果这个数存在 
    			res = max(res, i - b[s[i]]);
    	
    	cout << res;
    	return 0;
    }
    //前缀和做法,
    //首先开一个数组a,将所有输入的数取模  
    //再开一个前缀和数组s,将所有前缀和对7取模
    //再开一个数组b,用来记录0~6第一次分别出现的位置
    //然后遍历前缀和数组,如果上面对7取模的结果存在,那么就用当前位置i减去s[i]第一次出现的位置就可以了。
    //或者已经为0,也就是前缀和本身是7的倍数,那此时长度就是i;
    //比较最大的结果res;
    
  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/yuanyulin/p/14026727.html
Copyright © 2011-2022 走看看