小白月赛71(3/6)

这次小白月赛前三题是真的简单,9分钟前三道题目都过了,然后剩下的1小时50分钟一直在罚座,不得不说后面的几道题目难度还是很大的....最重要的是我太菜了....经过这场小白月赛,我rating直接加了170,成为了蓝名,rating1226,向绿名前进吧....

ABC纯纯的签到题这里就不说了,不过C题数据可能超long long,所以可以用double或者int128(我不会...)

D:登录—专业IT笔试面试备考平台_牛客网

很恶心的一道模拟题目,

1≤n,m≤2⋅105 ,双层循环肯定会超时,所以需要模拟的优化,我想过二分,但是贪心的做法比二分更优。

我的思路是先将主人的友好度从大到小排序,然后主人的期待友好值从小到大排序,

然后就可以双层循环,结果还是超时...从

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
struct Node{
	int a,c;
}x[200005];
struct Node1{
	int b,d;
}y[200005];
bool cmp(Node1 s1,Node1 s2){
	if(s1.b!=s2.b)return s1.b>s2.b;
	return s1.d<s2.d;
}
int n,m;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&x[i].a);
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&x[i].c);
	}
	for(int i=1;i<=m;i++){
		scanf("%d",&y[i].b);
	}
	for(int i=1;i<=m;i++){
		scanf("%d",&y[i].d);
	}
	sort(y+1,y+1+m,cmp);
	for(int i=1;i<=n;i++){
		int flag=0;
		for(int j=1;j<=m;j++){
			if(y[j].b>=x[i].c&&x[i].a>=y[j].d){
				flag=1;
				printf("%d ",y[j].b);
				break;
			}
			if(y[j].b<x[i].c){
				break;
			}
		}
		if(flag==0){
			printf("-1 ");
		}
	}
	
	return 0;
}

 超时之后就只能再优化了,我考虑到可能有许多主人的友好值是相同的,而且我们的排序是将主人的期待友好值从小到大排序的,如果第一个主人不行,那么与他友好值相同的都不行,所以可以用一个s数组来记录没一个友好值的第一个主人。我感觉这样是可行的..结果还是不行...

	#include<cstdio>
	#include<cmath>
	#include<iostream>
	#include<algorithm>
	#include<cstring>
	#include<queue>
	#include<stack>
	#include<deque>
	#include<vector>
	#include<map>
	#include<set>
	#include <utility>
	using namespace std;
	typedef  long  long ll ;
	#define pii pair<int,int>
	const int inf = 0x3f3f3f3f;
	inline int read(){
	    int x = 0, f = 1;
	    char ch = getchar();
	    while(ch < '0' || ch > '9'){
	        if (ch == '-')
	            f = -1;
	        ch = getchar();
	    }
	    while(ch >= '0' && ch <= '9'){
	        x = (x<<1) + (x<<3) + (ch^48);
	        ch = getchar();
	    }
	    return x * f;
	}
	void print(__int128 num) {
		if(num) {
			print(num/10);
			putchar(num%10+'0');
		}
	}
	struct Node{
		int a,c;
	}x[200005];
	struct Node1{
		int b,d;
	}y[200005];
	bool cmp(Node1 s1,Node1 s2){
		if(s1.b!=s2.b)return s1.b>s2.b;
		return s1.d<s2.d;
	}
	int n,m;
	int s[200005];
	int main(){	
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&x[i].a);
		}
		for(int i=1;i<=n;i++){
			scanf("%d",&x[i].c);
		}
		for(int i=1;i<=m;i++){
			scanf("%d",&y[i].b);
		}
		for(int i=1;i<=m;i++){
			scanf("%d",&y[i].d);
		}
		sort(y+1,y+1+m,cmp); 
		s[1]=1;
		int num=2;
		for(int i=2;i<=m;i++){
			if(y[i].b!=y[i-1].b){
				s[num]=i;
				num++;
			}
		}
		for(int i=1;i<=n;i++){
			int flag=0;
			for(int j=1;j<=num-1;j++){
				if((y[s[j]].b>=x[i].c)&&(x[i].a>=y[s[j]].d)){
					printf("%d ",y[s[j]].b);							
					flag=1;			
					break;
				}
				if(y[s[j]].b<x[i].c){													
					printf("-1 ");					
					flag=1;
					break;
				}
			}
			if(flag==0){
				printf("-1 ");
			}
			
		}	
		return 0;
	}

正确思路是:离线询问(就是没必要按照猫的循环来询问,可以不按顺序询问,最后再按顺序输出即可)

因为猫和主人都有两种状态,所以很容易想到,把他们的状态用二维坐标轴来表示(很容易想到吗...其实很难啊)

 对于一个猫的状态点(a,c),满足条件的点再在(a,c)点的左上方,我们要求的点就是纵坐标最大的点;

这题可以用双指针我是真的没想到...在加上离线询问,就可以了....

把主人的期待友善值从小到大排序,猫的友善值从大到小排序

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
	#include<map>
	#include<set>
	#include <utility>
	using namespace std;
	typedef  long  long ll ;
	#define pii pair<int,int>
	const int inf = 0x3f3f3f3f;
	inline int read(){
	    int x = 0, f = 1;
	    char ch = getchar();
	    while(ch < '0' || ch > '9'){
	        if (ch == '-')
	            f = -1;
	        ch = getchar();
	    }
	    while(ch >= '0' && ch <= '9'){
	        x = (x<<1) + (x<<3) + (ch^48);
	        ch = getchar();
	    }
	    return x * f;
	}
	void print(__int128 num) {
		if(num) {
			print(num/10);
			putchar(num%10+'0');
		}
	}
int n,m;
struct Node{
	int x,y,id;
}cat[200005],host[200005];
int ans[200005];
bool cmp(Node a,Node b){
	return a.x<b.x;
}
int main(){	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&cat[i].x);
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&cat[i].y);
	}
	for(int i=1;i<=m;i++){
		scanf("%d",&host[i].y);
	}
	for(int i=1;i<=m;i++){
		scanf("%d",&host[i].x);
	}
	for(int i=1;i<=n;i++){
		cat[i].id=i;
	}
	sort(cat+1,cat+1+n,cmp);
	sort(host+1,host+1+m,cmp);
	int maxn=-1;
	int r=1;
	for(int i=1;i<=n;i++){
		while(r<=m&&host[r].x<=cat[i].x){
			maxn=max(maxn,host[r].y);
			r++;
		}
		if(cat[i].y<=maxn){
			ans[cat[i].id]=maxn;
		}else{
			ans[cat[i].id]=-1;
		}
	}
	for(int i=1;i<=n;i++){
		printf("%d ",ans[i]);
	}
	return 0;
}

E:

前三道题目作出自信了,想着我一定要ak,然后做这题就开始瞎做...

结果是不可能过的..

正确思路:更相损减法,gcd(a,b)加入a>b,那么gcd(a,b)=gcd(a-b,b);

所以gcd(a+c,b+c)=gcd(a-b,b+c);

因为a-b的最大值为1e15,所以可以枚举a-b的所有因数,时间复杂度为O(logn),不会超时

但需要注意特判如果a-b==0说明a为最大公约数,如果a==1,c就等于1,因为题目要求的是最大共约数不为1,所以a+c==b+c==2,最大共约数为2,如果a-b==0并且a不为1,那么直接输出a就可以了;

如果a-b==1说明最大公约数为1,不存在满足条件的c。

其他的情况就需要枚举a-b的所有因子了,但需要注意的需要维护c的值

对于a-b的一个因子x,假如x为1,就直接退出,如果b%x==0,说明x也是b的因子,ans=0,直接退出循环即可;否则,(b+c)%x==0,所以c==x-b%x;

更相损减法:

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int x,y; 
int gcd(int a,int b){
	if(a==b)return a;
	if(a>b){
		return gcd(a-b,b);
	}
	return gcd(a,b-a);	
}
int main(){
	scanf("%d%d",&x,&y);
	if(x<y)swap(x,y);
	int n=gcd(x,y);
	printf("%d",n);
	return 0;
}

 正确代码:

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef  long  long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
ll a,b;
ll ans=1e16;
void check(ll x){
	if(x==1)return ;
	if(b%x==0){
		ans=min(ans,(ll)0);
	}else{
		ans=min(ans,x-b%x);
	}
}
int main(){
	cin>>a>>b;
	if(a<b)swap(a,b);
	ll d=a-b;
	if(d==0){
		if(a==1){
			printf("1\n");
			return 0;
		}else{
			printf("0\n");
			return 0;
		}
	}
	if(d==1){
		printf("-1\n");
		return 0;
	}
	for(int i=1;i<=sqrt(d)+1;i++){
		if(d%i==0){
			check(i);
			check(d/i);
			if(ans==0)break; 
		}
	}
	printf("%lld\n",ans);
	return 0;
}

这场小白月赛是2023.4.21打的,4.22是天梯赛,打完就感觉自己明天天梯赛稳了,结果天梯赛直接拉跨,84分,全队最低,坑了队友...真是不想回忆啊..

然后就军训了七天,七天的时间一点也没摸代码,现在才开始补题,真是不想回忆啊....

写完这篇题解开始补天梯赛的题了,这该死的回忆啊...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值