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)
a3−b3=(a−b)∗(a2+ab+b2)
很显然如果
a
3
−
b
3
a^3-b^3
a3−b3 要为质数,则
a
−
b
a-b
a−b 应等于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;
}