MoniCompet

2021/6/12 模拟赛报告 二分/决策/并查集

T1 立方差数

题目大意:给定n个质数,请你判断它们是否为两个数的立方差,是输出YES,不是输出NO
首先我们都知道立方差公式是这个↓
                                      a 3 − b 3 = ( a − b ) ∗ ( a 2 + a b + b 2 ) a^3-b^3 = (a-b)*(a^2+ab+b^2) a3b3=(ab)(a2+ab+b2)
很显然如果 a 3 − b 3 a^3-b^3 a3b3 要为质数,则 a − b a-b ab 应等于1, a 2 + a b + b 2 a^2+ab+b^2 a2+ab+b2应等于这个质数
所以有两种思路:
1.打表二分查找(题目数据打表57w)
2.二分答案运用上面的思路(- - - 本 人 采 用 - - -)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string> 
#define ll long long
using namespace std;
inline ll Read(){
	ll ans = 0;
	char ch = getchar(),las = ' ';
	while(!isdigit(ch)){las = ch;ch = getchar();}
	while(isdigit(ch)){ans = (ans<<3)+(ans<<1)+ch-'0';ch = getchar();}
	if(las == '-')ans = -ans;
	return ans;
}
inline void Write(ll x){
	if(x<0){x = -x;putchar('-');}
	if(x>=10)Write(x/10);
	putchar(x%10+'0');
}
ll solve(ll x){
	return 3*x*x+3*x+1;
}
int main(){
	//freopen("cubicp.in","r",stdin);
	//freopen("cubicp.out","w",stdout);
	int T;
	T = Read();
	for(int x = 1 ; x <= T ; ++x){
		ll X;
		X = Read();
		ll l = 1 , r = 2e9;
		while(l<r){
			ll mid = (l+1+r)>>1;
			if(solve(mid)<=X)l = mid;
			else r = mid-1;
		}
		if(solve(l)==X)printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

T2

本人不会~~~~~~~~~~~~~~~

T3 猜数字 二分/并查集

首先我们要知道并查集是个什么东西
推荐→并查集

并查集本题主要运用初始化init和查询祖先find
所有的话都在代码里了…

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
const int N = 10010;
//一、输入输出优化 
inline ll Read(){
   ll ans = 0;
   char ch = getchar(),las = ' ';
   while(!isdigit(ch)){las = ch;ch = getchar();}
   while(isdigit(ch)){ans = (ans<<3)+(ans<<1)+ch-'0';ch = getchar();}
   if(las == '-')ans = -ans;
   return ans;
}//-----快速读入-----//

inline void Write(ll x){
   if(x<0){x = -x;putchar('-');}
   if(x>=10)Write(x/10);
   putchar(x%10+'0');
}//-----快速输出-----//

//二、变量定义
int pre[N];//上级//
int n,t;//ntr!!!awa!!!//
struct node{
   int left;
   int right;
   int number;
}point[N],POINT[N];//定义包含每一组数据的结构体 要开两个要不然顺序会变 

//三、函数 
inline bool cmp(node a,node b){
   return a.number > b.number;
}//按照数字从大到小排序//

void init_BCJ(int n){
   for(int i = 1 ; i <= n ; i++){
   	pre[i] = i;
   }
}//初始化并查集//

int find(int x){
   if(pre[x] == x)return x;
   return pre[x] = find(pre[x]);
}//并查集路径压缩查找//

inline bool check(int k){
   int x,y,lmin,lmax,rmin,rmax;
   init_BCJ(n+1);
   for(int i = 1 ; i <= k ; i++){
   	point[i].left = POINT[i].left;
   	point[i].right = POINT[i].right;
   	point[i].number = POINT[i].number;
   }
   sort(point+1,point+1+k,cmp);
   lmin = lmax = point[1].left;
   rmin = rmax = point[1].right;
   for(int i = 2 ; i <= k ; i++){
   	if(point[i].number < point[i-1].number){
   		if(find(lmax) > rmin) return 1;
   		for(int j = find(lmin) ; j <= rmax ; j++){
   			pre[find(j)] = find(rmax+1);
   		}
   		lmin = lmax = point[i].left;
   		rmin = rmax = point[i].right;
   	}
   	else{
   		lmin = min(lmin,point[i].left);lmax = max(lmax,point[i].left);
   		rmin = min(rmin,point[i].right);rmax = max(rmax,point[i].right);
   		if(lmax > rmin)return 1;
   	}
   }
   if(find(lmax)>rmin)return 1;
   return 0;
}//核心check 

void join(int x,int y){
   int fx = find(x),fy = find(y);
   if(fx != fy){
   	pre[fx] = fy;
   }
}//并查集换老大,这个题并没有什么卵用// 

int main(){
   //1.INIT
   n = Read();t = Read();
   for(int i = 1 ; i <= t ; i++){
   	POINT[i].left = Read();
   	POINT[i].right = Read();
   	POINT[i].number = Read();
   }
   //2.Break_Two
   int l = 1,r = t,ans = 0,mid;
   while(l <= r){
   	mid = (l+r)>>1;
   	if(check(mid)){
   		ans = mid;
   		r = mid-1;
   	}
   	else{
   		l = mid+1;
   	}
   } 
   //3.PRINTF HAPPY AC
   Write(ans);
   return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值