• 牛客IOI周赛20-普及组


    牛客IOI周赛20-普及组

    完全数


    牛客的签到题,最暴力的做法就是把数每个因子罗列出来,但是这样只有60的暴力分,我们从题目的数据可以看到
    数据范围是1e7的,在学习素数的时候我们知道一个因子就能推出另一个因子,所以我们没必要从1判断到n-1
    直接i*i <= n就能找到所有的因子,但是注意像16这样的数,当我们的i为4的时候,这个4的因子只能算一次
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	long long  n;
    	scanf("%lld",&n);
    	long long  sum = 1;
    	for(long long  i = 2; i * i <= n; ++i) {
    		if(n % i == 0)
    			sum += n/i == i? 0 : n/i + i ;//判断是否是重因子
    	}
    	if(sum > n) {
    		puts("Late");
    	} else if(sum == n) {
    		puts("Pure");
    	} else if(sum < n) {
    		puts("Early");
    	}
    	return 0;
    }
    

      

    移动撤销


    解题思路:这个题是一个模拟题,我们先记录牛牛的操作,然后在记录的时候每次遇到Z,就把上一个操作删掉
    最后直接按照没有Z的操作模拟,然后输出最终的坐标,注意这里的Z,可能Z的上一个位置没有任何操作,用栈的同学请注意空栈的情况
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	int n;
    	vector<char> V;
    	char c;
    	cin >> n;
    	for(int i = 0; i < n; ++i) {
    		cin>>c;
    		if(c == 'Z') {
    			if(V.size())//当V不为空的时候才进行撤销操作
    				V.pop_back();
    		} else {
    			V.push_back(c);
    		}
    	}
    	int x,y;
    	x = y = 0;
    	for(int i = 0; i < V.size(); ++i) {//直接模拟
    		if(V[i] == 'W') {
    			y++;
    		} else if(V[i] == 'A') {
    			x--;
    		} else if(V[i] == 'S') {
    			y--;
    		} else if(V[i] == 'D') {
    			x++;
    		}
    	}
    	cout << x << " " << y << endl;//最后输出x和y
    	return 0;
    }
    

      

    石头剪刀布


    解题思路:牛牛要想分数拿的高,那么就要尽可能的不输,我们可以计算牛牛最多能赢的场数,然后再把赢的场数从游戏场数剪掉
    然后再计算平局可能的场数就是最高的分数,然后……然后就AC了呀
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	int n;
    	cin>>n;
    	int a1,b1,c1;
    	int a2,b2,c2;
    	cin>>a1>>b1>>c1;
    	cin>>a2>>b2>>c2;
    	int win1,win2,win3;//这是牛牛可能会赢的场数(分别对应着石头、剪刀、布)
    	long long sum = 0;
    	win1 = min(a1,b2);
    	win2 = min(b1,c2);
    	win3 = min(c1,a2);
    	sum += win1 * 2;
    	sum += win2 * 2;
    	sum += win3 * 2;
    	a1 -= win1;//这里分别减去牛牛赢的场数
    	b2 -= win1;
    	b1 -= win2;
    	c2 -= win2;
    	c1 -= win3;
    	a2 -= win3;
    	sum += min(a1,a2) + min(b1,b2) + min(c1,c2);//最后再把可能平局的场数加起来就好啦
    	cout<<sum<<endl;
    	return 0;
    }
    

      

    夹缝中求和


    解题思路:我们要求范围在X和Y之间的不同数的两两组合,且i<j,很明显数的位置不重要,我们就可以队数组进行排序操作
    然后我们枚举i,找到满足条件的aj的范围,aj的范围是X到Y的,所以我们可以用二分查询找到j的范围(因为前面排过序了)
    Code:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 100005;
    int a[N];
    
    int find(int l,int r,int key)
    {
    	while(l+1<r)
    	{
    		int mid=l+r>>1;
    		if(a[mid]<=key)
    		l=mid;
    		else
    		r=mid;
    	}
    	return r;
    }
    
    int main()
    {
    	int n,x,y;
    	scanf("%d%d%d",&n,&x,&y);
    	for(int i = 0;i < n; ++i) {
    		scanf("%d",&a[i]);
    	}
    	long long sum = 0;
    	sort(a,a+n);
    	for(int i = 0;i < n; ++i) {
    		int k1 = x - a[i];
    		int k2 = y - a[i];
    		int loc1 = max(i+1,find(-1,n,k1 - 1));//找到满足条件的左边的位置
    		int loc2 = max(loc1,find(-1,n,k2));//右边的位置
    		sum += max(0,loc2 - loc1);
    	}
    	printf("%lld
    ",sum);
    	return 0;
    }
    

    当然这题还能用双指针做,但是不知道为什么我的双指针写出来炸了,然后写了个'单指针'?hh
    如果但看这个左边界或者有边界的话,我们可以直接写出一个0(N)的操作,然后我们会发现这样写的话会有值的重叠
    所以我们直接把考虑右边界的情况减去左边界的情况就OK啦,不懂的话可以手算一下哦
    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 100005;
    int a[N];
    
    int main()
    {
    	int n,x,y;
    	scanf("%d%d%d",&n,&x,&y);
    	for(int i = 0;i < n; ++i) {
    		scanf("%d",&a[i]);
    	}
    	sort(a,a+n);
    	int l = 0, r = 0;
    	long long sum = 0;
    	for(int i = 0, j = n - 1 ;i < n; ++i) {//计算的是只考虑有边界的情况
    		while(j > 0 && a[i] + a[j] > y) j--;
    		if(j < i) break;
    		sum += j - i;
    	}
    	for(int i = 0, j = n - 1 ;i < n; ++i) {//计算的是只考虑左边界的情况
    		while(j > 0 && a[i] + a[j] >= x) j--;
    		if(j < i) break;
    		sum -= j - i;
    	}
    	
    	printf("%lld
    ",sum);
    	
    }
    

      
    第一次AK,++rp;

  • 相关阅读:
    我开发过程中用到的工具
    我最近写的DataGrid合并/删除相同列通用函数,跟大家分享
    开源项目- Archive Explorer
    SQLite准备出3.0了!
    软件缺陷管理指南 3
    介绍一些.net好站点
    几个著名java开源缓存系统的介绍
    SQL中的Where,Group By,Order By和Having的用法/区别
    Unix/Linux中Cron的用法
    java中判断字符串是否为纯数字
  • 原文地址:https://www.cnblogs.com/Mangata/p/14061050.html
Copyright © 2020-2023  润新知