[旧文章补档]数学相关

#快速幂#

int qpow(int x,int k,int p)
{
	int ans=1;
	for(;k;x=x*x%p,k=k>>1)
		if(k&1) ans=(ans*x)%p;
	return ans;
}

#线性筛#

void get_prime(bool mk[],int p[],int mn[],int n)
{
	for(int i=2;i<=n;i++)
	{
		if(!mk[i]) p[++p[0]]=i,mn[i]=p[0];
		for(int j=1;j<=p[0]&&i*p[j]<=n;j++)
		{
			mk[i*p[j]]=1;
			mn[i*p[j]]=j; //最小质因数
			if(i%p[j]==0)break;
		}		
	}
}

#线性求欧拉函数#

void get_phi()
{
	phi[1]=1;
	for(int i=2;i<=N;i++)
	{
		if(!mk[i]) p[++cnt]=i,phi[i]=i-1;//i为素数
		for(int j=1;j<=cnt&&p[j]*i<=N;j++)
		{
			mk[i*p[j]]=1;
			if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;}
			//如果i%p=0 phi(i*p)=p*phi(i) 证明见下方
			else phi[i*p[j]]=phi[i]*(p[j]-1);//欧拉函数为积性函数
		}
	}
}

先贴个链接。。有时间补上 证明
#线性求莫比乌斯函数#
跟上面差不多。。。

void get_mul(int n)
{
	mul[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!s[i]){p[++head]=i,mul[i]=-1;}
		for(int j=1;j<=head&&p[j]*i<=n;j++)
		{
			s[p[j]*i]=1;
			if(i%p[j]==0){mul[p[j]*i]=0;break;}
			else mul[p[j]*i]=-mul[i];
		}
	}
}
int cal(int n,int m,int k)
{
	n/=k,m/=k;
	int now=0,ans=0;
	for(int k=1;k<=min(n,m);k=now+1)
	{
		now=min(n/(n/k),m/(m/k));
		ans+=(sum[now]-sum[k-1])*(n/k)*(m/k);
	}
	return ans;
}

这里写图片描述

莫比乌斯反演 popoqqq Orz

#裴蜀定理#
若a,b是整数,且(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。 证明

#gcd & exgcd#

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
void exgcd(int a,int b,int &x,int &y)
{
	if(b==0){x=1,y=0;return;}
	exgcd(b,a%b,x,y);
	int t=x;x=y;y=t-a/b*y;
}
bool solve(int a,int b,int c,int &x,int &y)
{
	int d=gcd(b,c);
	if(c%d) return 0;//无解
	a/=d,b/=d,c/=d;
	exgcd(a,b,x,y);
	x*=c,y*=c;
	/*x+=b y-=a*/
	return 1;
}

#高斯消元#

bool guass(int **a,int n)//高斯消元
{
    int i=1,to;double t;//now为当前处理的行数
    for(int i=1;i<=n;i++) //消去并回代Xi
    {
        for(to=i;to<=n;to++)
            if(fabs(a[to][i])>eps) break;//找到Xi系数非0的一行
        if(to>n) continue;//Xi系数全为0
        if(to!=i)for(int j=1;j<=n+1;j++)
            swap(a[to][j],a[i][j]);//交换
        t=a[i][i];
        for(int j=1;j<=n+1;j++) a[i][j]/=t;//将Xi行所有的系数变为1
        for(int j=1;j<=n;j++)//j为1到n 回代与消去同时进行
        {
            if(j==i) continue;
            t=a[j][i];//倍数
            for(int k=1;k<=n+1;k++)
                a[j][k]-=t*a[i][k];
        }
    }
    for(int i=1;i<=n;i++)
        if(fabs(a[i][n+1])>eps) return 0;//出现 0=常数 的情况无解
    return 1;//有解
}

#费马小定理#
Fermat 证明

玄学判素数

bool judge(LL x)
{
	if(x==1) return 0;
	if(x==2) return 1;
	if(x%2==0) return 0;
	for(int i=1;i<=50;i++)
	{
		LL p=rand()%x;
		if(p==0) p++;
		if(fpow(p,x-1,x)!=1) return 0;
	}
	return 1;
}

#组合数取模#

##1.Lucas定理##
p为质数时 C(n,m)%p = C(n/p,m/p) * C(n%p,m%p) % p 证明
注意当a < b时 C(a, b) = 0

int C(int n,int m,int p)//C(n,m) mod p p为素数
{
	if(n<m) return 0;
	if(m>n-m) m=n-m;
	int s1=1,s2=1;
	for(int i=1;i<=m;i++) s1=s1*(n-i+1)%p;
	for(int i=1;i<=m;i++) s2=s2*i%p;
	return s1*qpow(s2,p-2,p)%p;//逆元
}
int lucas(int n,int m,int p)//lucas定理 
{
	if(!n||!m) return 1;
	return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}

##2.分解质因数##
当要求C(n ,m) % p 且p不为质数时 可以分解质因数来做。。

int n,m,ans=1;
int p[N+5],cnt[N+5],mn[N+5];
bool mk[N+5];
void get()
{
	for(int i=2;i<=N;i++)
	{
		if(!mk[i]) p[++p[0]]=i,mn[i]=p[0];
		for(int j=1;j<=p[0]&&i*p[j]<=N;j++)
		{
			mk[i*p[j]]=1;
			mn[i*p[j]]=j;
			if(i%p[j]==0)break;
		}		
	}
}
void add(int x,int f)
{
	while(x!=1)
	{
		cnt[mn[x]]+=f;
		x/=p[mn[x]];
	}
}
int qpow(int x,int k)
{
	int ans=1;
	while(k)
	{
		if(k&1) ans=ans*x%m;
		k=k>>1,x=x*x%m;
	}
	return ans;
}
int solve()
{
	int ans=1;
	for(int i=1;i<=p[0];i++)
		ans=ans*qpow(p[i],cnt[i])%m;
	return ans;
}

例题 BZOJ 1485 [HNOI2009]有趣的数列

#卡特兰数#

C(2n,n) - C(2n,n-1) 或 C(2n,n) / (n+1)
###讲解 & 应用###

求解模线性方程

x % M1 = R1 ①
x % M2 = R2 ②

x % Mn = Rn

方程①等价于存在K1 满足 x = K1 * M1 + R1
方程②等价于存在K2 满足 x = K2 * M2 + R2
K1 * M1 + R1 = K2 * M2 + R2
移项得
K1 * M1 - K2 * M2 = R2 - R1
a=M1 b=M2 c=R2-R1 用exgcd解出一个x
用这个x作为特解 扩展出一个解系
X = x + k*lcm(M1, M2)
即 X % lcm(M1, M2) = x
这样两个方程就合并成了一个方程
两两合并求出方程组的解即可

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
void exgcd(int a,int b,int &x,int &y)
{
	if(b==0){x=1,y=0;return;}
	exgcd(b,a%b,x,y);
	int t=x;x=y;y=t-a/b*y;
}
void solve()
{
	int n=read();
	int a1=read(),b1=read(),a2,b2;
	int a,b,c,x,y,d; bool flag=0;
	for(int i=1;i<n;i++)
	{
		a2=read(),b2=read();//Mi Ri
		if(flag) continue;   
		a=a1,b=a2,c=b2-b1,d=gcd(a,b);
		if(c%d){flag=1;continue;}
		else
		{
			a/=d,b/=d,c/=d;
			exgcd(a,b,x,y);
			x=(c*x%b+b)%b;
			b1=x*a1+b1;
			a1=a1*a2/d;
		}
	}
	if(flag) printf("-1\n");
	else printf("%d\n",b1);
}

例题 POJ 2891 Strange Way to Express Integers
#BSGS#
先贴个链接 Orz

map<int,int> mp;
int bsgs(int a,int b,int p)
{
	if(a%p==0) return -1;
	int m=(int)sqrt(p),am=qpow(a,m,p);//a^m%p
	mp.clear();
	b%=p;
	for(int j=1,t=b;j<=m;j++)
		t=t*a%p,mp[t]=j;
	for(int i=1,t=1;i<=m;i++)
	{
		t=t*am%p;
		if(mp[t]) return i*m-mp[t];
		if(t==b) return i*m; //j==0
	}
	return -1;
}

例题 BZOJ 2242 [SDOI2011]计算器
#FFT#
FFT算法学习笔记 FFT入门 Orz
//插值的时候别忘了除n

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <complex>
#define N 100005*4
using namespace std;
const double pi = M_PI;
typedef complex<double> cp;
int n,m;
cp a[N],b[N];
void fft(cp *a,int n,int f)
{
	if(n==1) return;
	cp x[(n>>1)+1],y[(n>>1)+1];
	cp w(1,0),wn(cos(2*pi/n),sin(f*2*pi/n));
	for(int i=0;i<(n>>1);i++)
		x[i]=a[i<<1],y[i]=a[i<<1|1];
	fft(x,n>>1,f);
	fft(y,n>>1,f);
	for(int i=0;i<(n>>1);i++)
	{
		a[i]=x[i]+w*y[i];
		a[i+(n>>1)]=x[i]-w*y[i];
		w*=wn;
	}
}
int readin()
{
	cin>>n>>m;
	for(int i=0;i<=n;i++)
		cin>>a[i].real();
	for(int i=0;i<=m;i++)
		cin>>b[i].real();
	m+=n;
	for(n=1;n<=m;n=n<<1);
}
int main()
{
	readin();
	fft(a,n,1);
	fft(b,n,1);
	for(int i=0;i<n;i++)
		a[i]*=b[i];
	fft(a,n,-1);
	for(int i=0;i<=m;i++)
		printf("%d ",int(a[i].real()/n+0.5));//插值的时候别忘了除n
	printf("\n");
	return 0;
}

模板 UOJ #34 多项式乘法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值