随我不断学习而持续更新
文章目录
1、质数的判定
试除法判定质数(只用循环sqrt(n)次)
bool is_prime(int n){
if(n < 2)return false;
for(int i = 2;i <= n/i; i++)
if(n%i == 0)return false;
return true;
}
2、质因数的分解
输出的是质因子及其个数
void divide(int n)
{
for(int i = 2;i <= n/i;i ++ )
if(n % i == 0)
{
int s=0;
while(n%i==0)
{
n/=i;
s++;
}
printf("%d %d",i,s);
}
if(n>1) printf("%d %d",n,1);
}
3、质数筛(埃式筛)
利用布尔值判定,再利用桶排序记录合数
int prime[];
bool st[];
void get_primes(int n)
{
for(int i = 2;i <= n;i ++ )
{
if(!st[i])
{
primes[cnt ++] = i;//记录质数
for(int j = i + i;j <= n;j += i) st[j] = true;//记录合数
}
}
}
4、质数(线性筛)//未学会
const int N=10000010;
int primes[N],cnt;
bool st[N];
void get_primes(int n)
{
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
5、求约数
试除法求约数
vector<int> get_divisors(int n)
{
vector<int>res;
for(int i=1;i<=n/i;i++)
if(n%i==0)
{
res.push_back(i);
if(i!=n/i) res.push_back(n/i);
}
sort(res.begin(),res.end());
return res;
}
6、约数个数
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+5;
int main()
{
int n;
cin>>n;
unordered_map<int,int>primes;//存底数和指数
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x;i++)
while(x%i==0)
{
x/=i;
primes[i]++;
}
if(x>1) primes[x]++;
}
long long res =1;
for(auto prime : primes) res = res * (prime.second +1)%mod;//循环用公式
//如果 N = p1^c1 * p2^c2 * ... *pk^ck
//约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
cout<<res<<endl;
return 0;
}
7、合并果子
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,c,ans,x,y;
priority_queue<int,vector<int>,greater<int> >vis;
cin>>n;
ans=0;
for(int i=1;i<=n;i++)
{
cin>>c;
vis.push(c);
}
while(vis.size()>1)
{
x=vis.top(); vis.pop();
y=vis.top(); vis.pop();
ans+=x+y;
vis.push(x+y);//注意不能直接将ans入堆,ans是最后的总和,而入堆的只是堆前两个数之和
}
cout<<ans<<endl;
vis.pop();
return 0;
}
8、约数的和
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+5;
int main()
{
int n;
cin>>n;
unordered_map<int,int>primes;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x;i++)
while(x%i==0)
{
x/=i;
primes[i]++;
}
if(x>1) primes[x]++;
}//求解约数结束
long long res =1;
for(auto prime : primes)//遍历求和开始
{
int p=prime.first,a=prime.second;
long long t=1;
while(a--)
t=(t*p+1)%mod;//题干要求,答案取模
res =res * t % mod;
}
cout<<res<<endl;
return 0;
}
9、求两个数的最大公约数
#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",gcd(a,b));
}
return 0;
}
10、快排模板
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
void quick_sort(int q[],int l,int r)
{
if(l >= r) return;//递归中止条件
int x=q[(l+r)/2],i=l-1,j=r+1;//最先取中间值为断点,i为左指针,j为右指针,因为在循环里先移动指针,所以i,j要多初始化一个单位
while(i<j)
{
do i++;while(q[i]<x);//当找到断点左边不小于x的值时循环结束
do j--;while(q[j]>x);//当找到断点右边不大于x的值时循环结束
if(i<j) swap(q[i],q[j]);//交换两个值
}
quick_sort(q,l,j);//递归继续排序
quick_sort(q,j+1,r);
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);
quick_sort(q,0,n-1);
for(int i=0;i<n;i++) printf("%d ",q[i]);
return 0;
}
11、归并排序 //未学会
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N],tmp[N];
void merge_sort(int q[],int l,int r)
{
if(l >= r) return;
int mid = (l + r)>> 1;
merge_sort(q,l,mid),merge_sort(q,mid + 1,r);//谜一样的递归排序
int k = 0,i = l,j = mid + 1;
while(i <= mid && j <= r)
if(q[i] <= q[j]) tmp[k ++ ]=q[i ++ ];
else tmp[k ++ ]=q[j ++ ];
while(i <= mid) tmp[k ++ ]=q[i ++];
while(j <= r) tmp[k ++ ]=q[j ++];
for(i =l,j=0;i<=r;i++,j++) q[i] = tmp[j];
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);
merge_sort(q,0,n-1);
for(int i=0;i<n;i++) printf("%d ",q[i]);
return 0;
}
12、整数二分
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,m;
int q[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);
while(m--)
{
int x;
scanf("%d",&x);
int l = 0,r = n - 1;
while(l<r)
{
int mid = l+r >>1;
if(q[mid]>=x) r=mid;//向左逼近答案
else l=mid+1;
}
if(q[l]!=x) cout<<"-1 -1"<<endl;
else
{
cout<<l<<' ';
int l=0,r=n-1;
while(l<r)
{
int mid=l+r+1 >>1;//需要加一,防止边界问题死循环
if(q[mid]<=x) l=mid;//向右逼近答案
else r=mid -1;
}
cout<<l<<endl;
}
}
return 0;
}
13、浮点数二分
求一个数的平方根
#include <bits/stdc++.h>
using namespace std;
int main()
{
double x;
cin>>x;
double l = 0,r=x;
while(r-l>1e-6)
{
double mid = (l+r)/2;
if(mid*mid>=x) r=mid;
else l=mid;
}
printf("%lf\n",l);
return 0;
}
14、高精度模板
模拟计算的过程
将数据存到数组里
加法:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
vector<int> add(vector<int> &A,vector<int> &B)
{
vector<int>C;
int t=0;
for(int i=0;i<A.size()||i<B.size();i++)
{
if(i<A.size()) t+=A[i];
if(i<B.size()) t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t) C.push_back(1);
return C;
}
int main()
{
string a,b;
vector<int>A,B;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
auto C = add(A,B);
for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
return 0;
}
减法:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool cmp(vector<int> &A,vector<int> &B)
{
if(A.size()!=B.size()) return A.size() > B.size();
for(int i=A.size()-1;i>=0;i--)
if(A[i] != B[i])
return A[i] > B[i];
return true;
}
vector<int> sub(vector<int>&A,vector<int>&B)
{
vector<int>C;
for(int i = 0,t=0;i<A.size();i++)
{
t=A[i]-t;
if(i<B.size()) t-=B[i];
C.push_back((t+10)%10);
if(t<0) t=1;
else t=0;
}
while(C.size() > 1&& C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a,b;
vector<int>A,B;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
if(cmp(A,B))
{
auto C = sub(A,B);
for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
}
else
{
auto C = sub(A,B);
printf("-");
for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
}
return 0;
}
乘法:
#include <bits/stdc++.h>
using namespace std;
vector<int> mul(vector<int> &A,int b)
{
vector<int>C;
int t=0;
for(int i = 0;i<A.size()||t;i++)
{
if(i<A.size()) t += A[i]*b;
C.push_back(t%10);
t/=10;
}
return C;
}
int main()
{
string a;
vector<int>A;
int b;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
auto C = mul(A,b);
for(int i=C.size() -1;i>=0;i--) printf("%d",C[i]);
return 0;
}
除法:
#include <bits/stdc++.h>
using namespace std;
vector<int> div(vector<int> &A,int b,int &r)
{
vector<int>C;
r=0;
for(int i= A.size()-1;i>=0;i--)
{
r=r*10+A[i];
C.push_back(r/b);
r%=b;
}
reverse(C.begin(),C.end());
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main()
{
string a;
vector<int>A;
int b;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
int r;
auto C = div(A,b,r);
for(int i=C.size() -1;i>=0;i--) printf("%d",C[i]);
cout<<endl<<r<<endl;
return 0;
}
15、前缀和
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,m;
int a[N],s[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) s[i] = s[i-1] + a[i];
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",s[r] - s[l-1]);
}
return 0;
}
二维前缀和:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n,m,q;
int a[N][N],s[N][N];
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j] = s[i-1][j] + s[i][j -1]-s[i-1][j-1] +a[i][j];
while(q--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",s[x2][y2] - s[x1-1][y2] - s[x2][y1- 1]+s[x1-1][y1-1]);
}
return 0;
}
16、差分//未学会
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n,m;
int a[N],b[N];
void insert(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) insert(i,i,a[i]);
while(m--)
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
insert(l,r,c);
}
for(int i=1;i<=n;i++) b[i] += b[i-1];
for(int i=1;i<=n;i++) printf("%d",b[i]);
return 0;
}
17、双指针算法
for(i=0,j=0;i<n;i++)
{
while(j<i&&check(i,j))j++;
//每道题目的具体逻辑
}
18、离散化//不太会
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N = 300010;
int n,m;
int a[N],s[N];
vector<int> alls;
vector<PII> add,query;
int find(int x)//一个二分查找的过程
{
int l=0,r=alls.size()-1;
while(l<r)
{
int mid = l+r >> 1;
if(alls[mid]>=x) r=mid;
else l=mid + 1;
}
return r+1;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)//记录插入数据
{
int x,c;
cin>>x>>c;
add.push_back({x,c});
alls.push_back(x);
}
for(int i=0;i<m;i++)//记录询问数据
{
int l,r;
cin>>l>>r;
query.push_back({l,r});
alls.push_back(l);
alls.push_back(r);
}
//去重
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//处理插入
for(auto item : add)
{
int x=find(item.first);
a[x] += item.second;
}
//处理前缀和
for(int i=1;i<=alls.size();i++) s[i] = s[i - 1]+a[i];
//处理询问
for(auto item : query)
{
int l = find(item.first),r = find(item.second);
cout<<s[r] - s[l - 1]<<endl;
}
return 0;
}
19、单调栈
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int stk[N],tt;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
while(tt && stk[tt]>=x) tt --;
if(tt)printf("%d ",stk[tt]);
else printf("-1");
stk[++tt]=x;
}
return 0;
}