最大公约数和最小公倍数
inline ll gcd(ll a,ll b) {return b == 0? a:gcd(b, a % b);} //最大公因数
inline ll lcm(ll a,ll b) return a*b/gcd(a,b); //最小公倍数
用内联函数能够加快函数的运行速度。
最大公约数只需要利用辗转相除法即可。
两个数的乘积等于它们最小公倍数和最大公约数的乘积。
普通快速幂
这里提供一个我自己写的例题链接(例题来源于落谷)
【模板】普通快速幂(quick_pow)
ll quickpow(ll a, ll b, ll mode) ////a为底数,b为指数,mod为取模
{
ll sum = 1;
if(mode == 1)
return 0 ;
while (b) {
if (b & 1) {
sum = (sum * a) % mode;
b--;
}
b /= 2;
a = a * a % mode;
}
return sum;
}
sort排序模板
这个函数在c++中有库函数帮我们实现,这们就不需要我们自己来编程进行排序了。
sort 函数的使用需要一个新的头文件#include <algorithm>
这个排序的效率比冒泡排序和选择排序的效率高多了。它使用的排序方法是类似于快排的方法,时间复杂度为n*log2(n),执行效率较高。
sort(start,end) ;//升序
inline bool cmp(ll a , ll b) return a>b
sort(start,end,cmp) ; //降序
这里的start 和end指的是数组里面的初始位置
例如对长度为n 的a[n]数组排序就为:
sort(a,a+n) ; //升序
既然这里还提到了快速排序,原理什么的我在这边就不细讲了,我就提供一下快速排序的模板
题目链接:P1177 【模板】快速排序
void quick_sort(ll a[],int left , int right)
{
if(left >= right)
return ;
int i = left, j = right ;
while(i < j)
{
while(j >i&&a[j] >=a[left])
j-- ;
while(i < j && a[i] <= a[left])
i++ ;
swap(a[i], (i == j) ? a[left] : a[j]);
}
quick_sort(a, left, i-1);
quick_sort(a, j+1, right);
}
并查集
并查集的核心就是压缩路径,找到目标的root 。
详见算法笔记
int find(int x){return (a[x]==x)? x:a[x]=find(a[x]);} //压缩路径
模板例题链接
(例题来源于洛谷)
AC代码如下:
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define T int t ;cin >> t;while(t--)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
inline ll gcd(ll a,ll b){return b == 0? a:gcd(b, a % b);}
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-11;
const ll mod = 1e9 + 7;
ll n, m ;
ll a[maxn] ;
int find(int x){
return (a[x]==x)? x:a[x]=find(a[x]);
}
int main()
{
scanf("%lld%lld",&n,&m) ;
ll z,x,y ;
for(int i =1 ; i <= n ; i++) a[i] = i ;
for(int i = 0 ; i < m ; i++){
scanf("%lld%lld%lld",&z,&x,&y) ;
if(z==1){
a[find(x)] = find(y) ;
}
else{
if(find(x) == find(y)){
printf("Y\n") ;
}
else{
printf("N\n") ;
}
}
}
return 0 ;
}
逆元
在求逆元的同时,快速幂也是离不开的。。
如果p是一个质数,而整数a不是p的倍数,则有a^(p-1)≡1(mod p)
ll quickpow(ll a, ll b, ll mode) ////a为底数,b为指数,mod为取模
{
ll sum = 1;
if(mode == 1)
return 0 ;
while (b) {
if (b & 1) {
sum = (sum * a) % mode;
b--;
}
b /= 2;
a = a * a % mode;
}
return sum;
}
ll inv(ll x) //逆元
{
return quickpow(x,mod-2,mod); //调用快速幂
}
大数
大数的核心思想就是将数字的运算变成数组里面实现
string sum(string s1,string s2) // 大数加大数
{
if(s1.length()<s2.length())
{
string temp=s1;
s1=s2;
s2=temp;
}
int i,j;
for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
{
s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));
if(s1[i]-'0'>=10)
{
s1[i]=char((s1[i]-'0')%10+'0');
if(i) s1[i-1]++;
else s1='1'+s1;
}
}
return s1;
}
string Multiply(string s,int x) //大数乘以整形数
{
reverse(s.begin(),s.end());
int cmp=0;
for(int i=0;i<s.size();i++)
{
cmp=(s[i]-'0')*x+cmp;
s[i]=(cmp%10+'0');
cmp/=10;
}
while(cmp)
{
s+=(cmp%10+'0');
cmp/=10;
}
reverse(s.begin(),s.end());
return s;
}
string Except(string s,int x) //大数除以整形数
{
int cmp=0,ok=0;
string ans="";
for(int i=0;i<s.size();i++)
{
cmp=(cmp*10+s[i]-'0');
if(cmp>=x)
{
ok=1;
ans+=(cmp/x+'0');
cmp%=x;
}
else{
if(ok==1)
ans+='0';
}
}
return ans;
}
string Multfa(string x,string y) //大数乘大数
{
string ans;
for(int i=y.size()-1,j=0;i>=0;i--,j++)
{
string tmp=Mult(x,y[i]-'0');
for(int k=0;k<j;k++)
tmp+='0';
ans=sum(ans,tmp);
}
return ans;
}
string Multiply(string s,long x) //大数乘整形数
{
reverse(s.begin(),s.end());
long cmp=0;
for(int i=0; i<s.size(); i++)
{
cmp=(s[i]-'0')*x+cmp;
s[i]=(cmp%10+'0');
cmp/=10;
}
while(cmp)
{
s+=(cmp%10+'0');
cmp/=10;
}
reverse(s.begin(),s.end());
return s;
}
string Remove_later(string s) //删除一个字符串的后倒0
{
int ok=1;
for(int i=s.size()-1; i>=0; i--)
{
if(s[i]=='0'){
s.erase(i);
}
else if(s[i]=='.')
{
s.erase(i);
ok=0;
}
else
ok=0;
if(ok==0)
break;
}
return s;
}
string factorial(string s,int n) //浮点数的n次方
{
if(n==0)
return "1";
string cmp="",count="";
long x=0,point=0;
for(int i=0; i<s.size(); i++)
if(s[i]!='.')
{
cmp+=s[i];
x=x*10+(s[i]-'0');
}
else
point=s.size()-1-i;
for(int i=1; i<n; i++)
{
cmp=Multiply(cmp,x);
}
int ans_point=cmp.size()-n*point;
if(ans_point<0)
{
count+='.';
for(int i=ans_point; i!=0; i++)
count+='0';
}
string::iterator it=cmp.begin();
if(ans_point>=0&&ans_point<cmp.size())
cmp.insert(it+ans_point,'.');
count+=(Remove_later(cmp));
return count;
}
string Remove_later(string s) //删除一个字符串的后倒0
{
for(int i=s.size()-1; i>=0; i--)
{
if(s[i]=='0')
s.erase(i);
else
break;
}
return s;
}