【SinGuLaRiTy-1047】 Copyright (c) SinGuLaRiTy 2017. All Rights Reserved.

质因数分解

void solve(int n)
{
while(n%==)
{
printf("%d*",);
n/=;
}
for(int i=;i<=sqrt(n);i+=)
{
if(n%i==)
{
n/=i;
printf("%d*",i);
i-=;
}
}
printf("%d\n",n);
}

欧拉线性筛素数

#define MAXN 100005
#define MAXL 1299710 int prime[MAXN];
int check[MAXL]; int tot=; void get_prime()
{
for(int i=;i<MAXL;i++)
{
if(!check[i])
prime[tot++]=i;
for(int j=;j<tot;j++)
{
if(i*prime[j]>MAXL)
break;
check[i*prime[j]]=;
if(i%prime[j]==)
break;
}
}
}

筛法求欧拉函数(线性)

#include<iostream>
#include<cstdio>
#define N 40000
using namespace std;
int n;
int phi[N+],prime[N+],tot,ans;
bool mark[N+];
void getphi()
{
int i,j;
phi[]=;
for(i=;i<=N;i++)//相当于分解质因式的逆过程
{
if(!mark[i])
{
prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。
phi[i]=i-;//当 i 是素数时 phi[i]=i-1
}
for(j=;j<=tot;j++)
{
if(i*prime[j]>N)
break;
mark[i*prime[j]]=;//确定i*prime[j]不是素数
if(i%prime[j]==)//接着我们会看prime[j]是否是i的约数
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[i]*(prime[j]-);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性
}
}
}

Miller-Rabbin素数判定法

#include<cstdlib>
#include<ctime>
#include<cstdio> using namespace std; const int count=; int modular_exp(int a,int m,int n)
{
if(m==)
return ;
if(m==)
return (a%n);
long long w=modular_exp(a,m/,n);
w=w*w%n;
if(m&)
w=w*a%n;
return w;
} bool Miller_Rabin(int n)
{
if(n==)
return true;
for(int i=;i<count;i++)
{
int a=rand()%(n-)+;
if(modular_exp(a,n,n)!=a)
return false;
}
return true;
} int main()
{
srand(time(NULL));
int n;
scanf("%d",&n);
if(Miller_Rabin(n))
printf("Probably a prime.");
else
printf("A composite.");
printf("\n");
return ;
}

倍增求快速幂

typedef long long ll;

ll fast_power(ll a,ll b,ll c)//求a^b%c
{
ll ans=;
while(b)
{
if (b&)
ans=ans*a%c;
else
ans%=c;
b>>=;
a=a*a%c;
}
return ans;
}

大数乘法取幂

typedef long long ll

ll qmul(ll x,ll y,ll mod)// 乘法防止溢出,如果p*p不爆LL的话可以直接乘;O(1)乘法或者转化成二进制加法(快速加)
{
ll ret=;
while(y)
{
if(y&)
ret=(ret+x)%mod;
x=x*%mod;
y>>=;
}
return ret;
} ll qpow(ll a,ll n,ll mod)
{
ll ret=;
while(n)
{
if(n&)
ret=qmul(ret,a,mod);
a=qmul(a,a,mod);
n>>=;
}
return ret;
}

GCD & LCM

LL gcd(LL a,LL b)
{
return b ? gcd(b,a%b) : a;
}

至于LCM=a*b/GCD,可能会因为a*b过大而爆掉,于是推荐使用LCM=a/GCD*b

Exgcd

求ax=b (mod m) ax+my=b 如果r=gcd(a,m)且b%r==0,则同余方程有解,其最小解为x*(b/r);
ax+by=c 如r=gcd(a,b),则存在x,y,使xa+yb=r;当x+=b,y-=a后仍然成立        
因为xa+yb+ab-ab=r;则(x+b)a+(y-a)b=r

int exgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=;
y=;
return a;
}
int r=exgcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}

中国剩余定理

设正整数m1,m2,m3...mk两两互素,则同余方程组

有整数解。并且在模M=m1·m2·...·mk下的解是唯一的,解为

其中,而的逆元。

void extend_Euclid(int a,int b,int &x,int &y)
{
if(b==)
{
x=;
y=;
return;
}
extend_Euclid(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-(a/b)*y;
} int CRT(int a[],int m[],int n)
{
int M=;
int ans=;
for(int i=;i<=n;i++)
M*=m[i];
for(int i=;i<=n;i++)
{
int x,y;
int Mi=M/m[i];
extend_Euclid(Mi,m[i],x,y);
ans=(ans+Mi*x*a[i])%M;
}
if(ans<)
ans+=M;
return ans;
}

Catalan数

f[]=;
for(int i=;i<=n;i++)
f[i]=f[i-]*(*i-)/(i+);

Catalan数有许多神奇的性质,这是一篇总结的比较精炼的文章。《Catalan数——卡特兰数》

康托展开式

int  fac[] = {,,,,,,,,}; //i的阶乘为fac[i]
// 康托展开-> 表示数字a是 a的全排列中从小到大排,排第几
// n表示1~n个数 a数组表示数字。
int kangtuo(int n,char a[])
{
int i,j,t,sum;
sum=;
for( i=;i<n;++i)
{
t=;
for(j=i+;j<n;++j)
if(a[i]>a[j])
++t;
sum+=t*fac[n-i-];
}
return sum+;
}

有啥用?它可以应用于哈希表中空间压缩。在码某些搜索题时,将VIS数组量压缩。比如:八数码魔板

求乘法逆元

exgcd,老熟人了。

/*
求解ax+by=gcd(a,b),亦即ax≡1(mod b)。函数返回值是a,b的最大公约数,而x即a的逆元。
注意a, b不能写反了。
*/
int x,y;
int extgcd(int a,int b,int &x,int &y)
{
if(b==)
{
x=;
y=;
return a;
}
int gcd=exgcd(b,a%b, x, y);
int tmp=x;
x=y;
y=tmp-(a/b)*y;
return gcd;
}

N的全排列

#include<iostream>

using namespace std;

void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
} void pai_xu(int a[],int m,int n)
{
if(m==n)
{
for(int i=;i<=n;i++)
cout<<a[i];
cout<<endl;
}
else
for(int i=m;i<=n;i++)
{
swap(a[i],a[m]);
pai_xu(a,m+,n);
swap(a[i],a[m]);
}
} int main()
{
int n,m=,a[];
cin>>n;
for(int i=;i<=n;i++)
a[i]=i;
pai_xu(a,m,n);
return ;
}

N的R排列

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath> using namespace std; bool b[]={};
int total=,a[]={}; bool pd(int x,int y)
{
int k=,i=x+y;
while(k<=sqrt(i)&&i%k!=)
k++;
if(k>sqrt(i))
return ;
else
return ;
} int print()
{
total++;
cout<<total<<" "<<endl;
for(int i=;i<=;i++)
cout<<a[i]<<" ";
cout<<endl;
} int search(int t)
{
for(int i=;i<=;i++)
if(pd(a[t-],i)&&(!b[i]))
{
a[t]=i;
b[i]=;
if(t==)
{
if(pd(a[],a[]))
print();
}
else
search(t+);
b[i]=;
}
} int main()
{
search();
cout<<total<<endl;
return ;
}

有重复元素的全排列

void fun(int n,char chars[],int flag) {
if(flag==n-) {
for(int i=;i<n;i++) cout<<chars[i];
cout<<endl;
return;
}
for(int i=flag;i<n;i++) {
if(chars[i]!=chars[flag]||i==flag){//若两个元素不相等或者两个元素的下标相同的时候才调用
swap(chars[i],chars[flag]);
fun(n,chars,flag+);
swap(chars[i],chars[flag]);
}
}
}

第一类Stirling数

定理:第一类Stirling数s(p,k)计数的是把p个对象排成k个非空循环排列的方法数。

证明:把上述定理叙述中的循环排列叫做圆圈。递推公式为:

s(p,p)=1 (p>=0)    有p个人和p个圆圈,每个圆圈就只有一个人

s(p,0)=0 (p>=1)    如果至少有1个人,那么任何的安排都至少包含一个圆圈

s(p,k)=(p-1)*s(p-1,k)+s(p-1,k-1)

设人被标上1,2,.....p。将这p个人排成k个圆圈有两种情况。第一种排法是在一个圆圈里只有标号为p的人自己,排法有s(p-1,k-1)个。第二种排法中,p至少和另一个人在一

个圆圈里。这些排法可以通过把1,2....p-1排成k个圆圈再把p放在1,2....p-1任何一人的左边得到,因此第二种类型的排法共有(p-1)*s(p-1,k)种排法。

在证明中我们所做的就是把{1,2,...,p}划分到k个非空且不可区分的盒子,然后将每个盒子中的元素排成一个循环排列。

long long s[maxn][maxn];//存放要求的第一类Stirling数
const long long mod=1e9+;//取模 void init()//预处理
{
memset(s,,sizeof(s));
s[][]=;
for(int i=;i<=maxn-;i++)
for(int j=;j<=i;j++)
{
s[i][j]=s[i-][j-]+(i-)*s[i-][j];
if(s[i][j]>=mod)
s[i][j]%=mod;
}
}

第二类Stirling数

定理:第二类Stirling数S(p,k)计数的是把p元素集合划分到k个不可区分的盒子里且没有空盒子的划分个数。

证明:元素在拿些盒子并不重要,唯一重要的是各个盒子里装的是什么,而不管哪个盒子装了什么。

递推公式有:S(p,p)=1 (p>=0)         S(p,0)=0  (p>=1)         S(p,k)=k*S(p-1,k)+S(p-1,k-1)   (1<=k<=p-1)。考虑将前p个正整数,1,2,.....p的集合作为要被划分的集合,把

{1,2,.....p}分到k个非空且不可区分的盒子的划分有两种情况:

(1)那些使得p自己单独在一个盒子的划分,存在有S(p-1,k-1)种划分个数

(2)那些使得p不单独自己在一个盒子的划分,存在有 k*S(p-1,k)种划分个数

考虑第二种情况,p不单独自己在一个盒子,也就是p和其他元素在一个集合里面,也就是说在没有放p之前,有p-1个元素已经分到了k个非空且不可区分的盒子里面(划

分个数为S(p-1,k),那么现在问题是把p放在哪个盒子里面呢,有k种选择,所以存在有k*S(p-1,k)。

long long s[maxn][maxn];//存放要求的Stirling数
const long long mod=1e9+;//取模 void init()//预处理
{
memset(s,,sizeof(s));
s[][]=;
for(int i=;i<=maxn-;i++)
for(int j=;j<=i;j++)
{
s[i][j]=s[i-][j-]+j*s[i-][j];
if(s[i][j]>=mod)
s[i][j]%=mod;
}
}

注意:要用long long类型,当元素个数>20,就超int类型了。

扩展:k! *S(p,k) 计数的是把p元素集合划分到k个可区分的盒子里且没有空盒子的划分个数。

组合数

//组合数打表模板,适用于N<=3000
//c[i][j]表示从i个中选j个的选法。
long long C[N][N];
void get_C(int maxn)
{
C[][] = ;
for(int i=;i<=maxn;i++)
{
C[i][] = ;
for(int j=;j<=i;j++)
C[i][j] = C[i-][j]+C[i-][j-];
//C[i][j] = (C[i-1][j]+C[i-1][j-1])%MOD;
}
}

LUCAS定理

long long F[];
void init(long long p)
{
F[] = ;
for(int i = ;i <= p;i++)
F[i] = F[i-]*i % ();
}
long long inv(long long a,long long m)
{
if(a == )return ;
return inv(m%a,m)*(m-m/a)%m;
}
long long Lucas(long long n,long long m,long long p)
{
long long ans = ;
while(n&&m)
{
long long a = n%p;
long long b = m%p;
if(a < b)return ;
ans = ans*F[a]%p*inv(F[b]*F[a-b]%p,p)%p;
n /= p;
m /= p;
}
return ans;
}

容斥原理

这个怎么打板呢?难道搞一道容斥的题?还是偷偷懒附个链接吧:

《算法中的容斥原理》

Time: 2017-11-05

[SinGuLaRiTy] 复习模板-数学的更多相关文章

  1. [SinGuLaRiTy] 复习模板-数据结构

    [SinGuLaRiTy-1040] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 二维线段树 2D_Segment_Tree //示例:单 ...

  2. [SinGuLaRiTy] 复习模板-搜索

    [SinGuLaRiTy-1043] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 桶排序 void bucketSort(int a[], ...

  3. [SinGuLaRiTy] 复习模板-高精度模板

    [SinGuLaRiTy-1042] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 结构体封装 //高精度运算 注意%I64d与%lld # ...

  4. [SinGuLaRiTy] 复习模板-图论

    [SinGuLaRiTy-1041] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 计算树的直径 //方法:任选一个点作为起点进行一次BFS ...

  5. 模板—数学—Exgcd

    模板—数学—Exgcd Code: #include <cstdio> #include <algorithm> using namespace std; int ex_gcd ...

  6. 模板—数学—Lucas

    模板—数学—Lucas Code: #include <cstdio> #include <algorithm> using namespace std; #define N ...

  7. django上课笔记4-复习数据库操作-复习模板-Seccion-详细cookie和session的区别

    一.复习数据库操作 字段类型 字符串 EmailField(CharField): IPAddressField(Field) URLField(CharField) SlugField(CharFi ...

  8. 算法模板の数学&数论

    1.求逆元 int inv(int a) { ) ; return (MOD - MOD / a) * inv(MOD % a); } 2.线性筛法 bool isPrime[MAXN]; int l ...

  9. 模板 - 数学 - 同余 - 扩展Euclid算法

    普通的扩展欧几里得算法,通过了洛谷的扩展欧几里得算法找乘法逆元.修复了容易溢出的bug,虽然新版本仍有可能会溢出longlong,假如参与运算的数字都是longlong,假如可以的话直接使用__int ...

随机推荐

  1. K:二叉树的非递归遍历

    相关介绍:  二叉树的三种遍历方式(先序遍历,中序遍历,后序遍历)的非递归实现,虽然递归方式的实现较为简单且易于理解,但是由于递归方式的实现受其递归调用栈的深度的限制,当递归调用的深度超过限制的时候, ...

  2. 抽象方法为什么不能被private与static修饰

    private private访问修饰符修饰的方法只能在本类当中使用.所以,必然不能用private去修饰抽象方法.抽象方法一定是要被子类去重写的. static Java中用static修饰符修饰的 ...

  3. windows 驱动开发入门——驱动中的数据结构

    最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...

  4. [认证授权] 6.Permission Based Access Control

    在前面5篇博客中介绍了OAuth2和OIDC(OpenId Connect),其作用是授权和认证.那么当我们得到OAuth2的Access Token或者OIDC的Id Token之后,我们的资源服务 ...

  5. [转] Web 开发模式演变历史和趋势

    文章转自梦想天空--前端文摘:Web 开发模式演变历史和趋势 一.简单明快的早期时代 可称之为 Web 1.0 时代,非常适合创业型小项目,不分前后端,经常 3-5 人搞定所有开发.页面由 JSP.P ...

  6. 【读书笔记】【深入理解ES6】#4-扩展对象的功能性

    对象类别 ES6规范清晰定义了每一个类别的对象. 普通(Ordinary)对象 具有JS对象所有的默认内部行为 特异(Exotic)对象 具有某些与默认行为不符的内部行为 标准(Standard)对象 ...

  7. MongoDB批量导入及简单的性能优化

    今天简单分享一下MongoDB使用过程中的一些性能优化,其实并不只适用MongoDB,其他数据库多少也可适用. 首先先随机导入一千万条数据.这里我分段导入的,因为mongo的BsonDocument一 ...

  8. linux 安装MySql 5.7.21 操作步骤

    一:到mysql官网下载最新的mysql包 mysql-5.7.21-linux-glibc2.12-x86_64 https://dev.mysql.com/downloads/mysql/ 二:在 ...

  9. 一个标准的WebView示例

    xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= ...

  10. Gym 101667I Slot Machines

    原题传送门 题意:给定n(n≤106)个数,要求将它化为混偱环小数的形式,即前k个数不参与循环,之后所有数以p为循环节长度进行循环.求k和p,要求k+p尽量小,k+p相等时要求p尽量小. 样例1 输入 ...