一些不知道怎么分类的记录

一、set

set用于去重,但set不光是可以对一维进行去重,同样也可以对组合进行去重

用法是结合pair来使用

【问题描述】

填空题

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。

给定平面上 2 × 3 个整点 {(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},即横坐标是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数的点。这些点一共确定了 11 条不同的直线。

给定平面上 20 × 21 个整点 {(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},即横坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0 和 20) 之间的整数的点。请问这些点一共确定了多少条不同的直线

#include <iostream>
#include<vector>
#include<set>
using namespace std;

int gcd(int a,int b)
{
	if(b==0)return a;
	else return gcd(b,a%b);
}
int main()
{
	set<pair<int,pair<int,int>>>t;
	for(int x1=0;x1<20;x1++){
		for(int y1=0;y1<21;y1++){
			for(int x2=0;x2<20;x2++){
				for(int y2=0;y2<21;y2++){
					if(x1 == x2 && y1 == y2) continue;
					int a=y1-y2;
					int b=x2-x1;
					int c=y2*x1-x2*y1;
					
					int d=gcd(a,gcd(b,c));

					a=a/d; b=b/d; c=c/d;
					t.insert({a,{b,c}});
				}
			}
		}
	}
    cout<<t.size();
}

二、求约数的小技巧

int zys(ll n){

	for(ll i=1;i<=n/i;i++){
		if(n%i==0){
			l[++t]=i;
			if(i*i!=n)l[++t]=n/i;
		}
	}
	return 1;
}

三、i & (1<<j)

  1<<j表示二进制表示的1(即0001)的所有位向左平移j个单位后的数,如j=1,则平移后的结果是0010,此时得到数2。若j=3,平移后的结果是1000,此时得到数8向左平移j位,即表示将原来的数乘上2^j可以类比十进制,所有位左移j位,相当于在后面添了j0,即乘上10^j,在二进制中,即乘上2^j

  &在此处表示按位与,即两个二进制表示的数,在对应位置上进行取并的操作,都为1时取1,否则取0。如1010(十进制的10)和0101(十进制的5)进行按位与操作后,得到的是0000(十进制的0)。

关于 i & (1<<j) 和 1 & (i>>j) 的解释 - unuliha - 博客园

四、并查集

俗称找父亲,这类题目难的关键点在于,在不给提示的前提下,你看不出来这是个并查集

https://www.lanqiao.cn/problems/185/learning/

给定一个长度为 NN 的数组 A = [A_1,A_2,··· ,A_N]A=[A1​,A2​,⋅⋅⋅,AN​],数组中有可能有重复出现的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A_2,A_3,··· ,A_NA2​,A3​,⋅⋅⋅,AN​。

当修改 A_iAi​ 时,小明会检查 A_iAi​ 是否在 A_1A1​ ∼ A_i−1Ai​−1 中出现过。如果出现过,则小明会给 A_iAi​ 加上 1 ;如果新的 A_iAi​ 仍在之前出现过,小明会持续给 A_iAi​ 加 1 ,直 到 A_iAi​ 没有在 A_1A1​ ∼ A_i−1Ai​−1 中出现过。

当 A_NAN​ 也经过上述修改之后,显然 AA 数组中就没有重复的整数了。

现在给定初始的 AA 数组,请你计算出最终的 AA 数组。

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int fa[100005],vis[100005];//fa[a]=b表示a的父亲是b 
int find(int a){
	if(a==fa[a])return a;
	return fa[a]=find(fa[a]);
}
int main(){
	int n,fat,t;
	cin>>n;
	for(int i=1;i<=100005;i++){
		fa[i]=i;
	}
	for(int i=1;i<=n;i++){
		cin>>t;
		if(vis[t]==1){
			fat=find(t)+1;
		}
		else fat=t;
		cout<<fat<<" ";
		vis[fat]=1;
		if(vis[fat-1]==1){//维护父亲数组,如果前面的用了,那么前面的父亲的父亲就是现在这个父亲 
			fa[fat-1]=fat;
		}
		if(vis[fat+1]==1){
			fa[fat]=fat+1;
		}
	}
	
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值