数论:
1.素数(质数)
①定义法:O(n)
n>=2 && i<=n-1
②性质法: O(sqrt(n))
成对出现
若d能整除n,那么n/d也能整除n
d 和n/d为一对
那么我们只要枚举到较小的即可
答案:d<=n/d,
dd<=n PS:这种写法不推荐 若n接近int最大值,那么dd有可能存在溢出风险
d<=sqrt(n) PS:这种写法不推荐 因为没次都要调用一次函数,效率低。
2.约数
与质数相对
做法与质数一样
并查集:
836. 合并集合
题目链接
与之前学的kruscal是一个道理的
#include<iostream>
using namespace std;
const int N=100000+10;
int n,m;
int father[N];
int find(int x){
return father[x]==x?x:father[x]=find(father[x]);
}
void my_union(int a, int b){
int xx=find(a);
int yy=find(b);
if(xx!=yy){
if(yy>xx){
father[yy]=xx;
}else{
father[xx]=yy;
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
father[i]=i;
}
while(m--){
char s[2];
int a,b;
cin>>s>>a>>b;
if(s[0]=='M'){
my_union(a,b);
}else{
if(find(a)==find(b)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
}
return 0;
}
并查集的扩展应用:
837. 连通块中点的数量
题目链接
在并查集原有代码的基础上改造。
#include<iostream>
using namespace std;
const int N=100000+10;
int n,m;
int father[N];
int se[N];
int find(int x){
return father[x]==x?x:father[x]=find(father[x]);
}
void my_union(int a, int b){
int xx=find(a);
int yy=find(b);
if(xx!=yy){
if(yy>xx){
se[xx]+=se[yy];
father[yy]=xx;
}else{
se[yy]+=se[xx];
father[xx]=yy;
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
father[i]=i;
se[i]=1;
}
while(m--){
char s[5];
int a,b;
cin>>s;
if(s[0]=='C'){
cin>>a>>b;
my_union(a,b);
}else if(s[1]=='1'){
cin>>a>>b;
if(find(a)==find(b)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}else{
cin>>a;
int f=find(a);
cout<<se[f]<<endl;
}
}
return 0;
}
240.食物链 并查集 练习题
ps:dp的递归形式 - 记忆化搜索 (区间dp写成递归比较好理解)