数论模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/79953573

1. 辗转相除法(欧几里得除法)

int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}

或者c++直接用函数__gcd()

2.扩展欧几里得

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

3.素数筛 —— NlogN

void getprime()
{
	int n=sqrt(m+0.5);
	memset(vis,false,sizeof vis);
	for(int i=2;i<=n;i++)
	{
		if(vis[i]==false)
		{
			for(int j=i*i;j<=n;j+=i)
			vis[j]=true;
		}
	}
}

vis数组中false为素数,可以1e7的数据量

欧拉筛(线性筛) —— N

void getprime()
{
	bool vis[100001000];
	int prime[1000100];//存所有的素数
	int pl=0;//prime数组的长度
	for(int i=2;i<=10000000;i++)
	{
		if(vis[i]==false)
		prime[++pl]=i;
		for(int j=1;j<=pl&&i*prime[j]<max_;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)
			break;
		}
	}
}

筛出后放到了prime数组中,最多可解1e8

4.二分递归求等比数列前n项和

a+a^2+a^3+...+a^n

①n为偶数

原式=(a+a^2+...+a^n/2)(1+a^n/2)

②n为奇数

原式=(a+a^2+...+a^n/2)(1+a^n/2+1)+a^n/2+1

ll f(ll p,ll n)
{
	if(n==0)
	return 1;
	if(n&1)
	return (f(p,n/2)*(1+fpow(p,n/2+1)))%mod+fpow(p,n/2+1)%mod;
	else
	return (f(p,n/2)*(1+fpow(p,n/2)))%mod;
}

1+a+a^2+...a^n

ll f(ll p,ll n) 
{  
    if(n==0)  
    return 1;  
    if(n&1)  
    return (f(p,n/2)*(1+fpow(p,n/2+1)))%mod;  
    else  
    return (f(p,n/2-1)*(1+fpow(p,n/2+1))%mod+fpow(p,n/2)%mod)%mod;  
}

 

5.算数基本定理(唯一分解定理)

 

可以证明,数x分解后的最大素数要么小于x要么幂为1,所以只要判到下即可,最后再特判结果是否为1,可减小时间复杂度

for(int i=2;i*i<=a;)
{
	if(tmp%i==0)
	{
		num[++pl]=i;
		flag=1;
	}
	while(tmp%i==0)
	{
		tmp/=i;
		cnt[pl]++;
	}
	if(tmp==1)
	break;
	if(i==2)
	i++;
	else
	i+=2;
}
if(tmp!=1)
{
	num[++pl]=tmp;
	cnt[pl]=1;
}

6.欧拉函数

void getphi()
{
	for(int i=1;i<max_;i++)
	{
		p[i]=i;
		if(i%2==0)
		p[i]>>=1;
	}
	for(int i=3;i<max_;i+=2)
	{
		if(p[i]==i)
		{
			for(int j=i;j<max_;j+=i)
			p[j]-=p[j]/i;
		}
	}
}
int phi(int n)  
{  
    int i,rea=n;  
    for(i=2;i*i<=n;i++)  
    {  
        if(n%i==0)  
        {  
            rea=rea-rea/i;  
            while(n%i==0)  n/=i;  
        }  
    }  
    if(n>1)  
        rea=rea-rea/n;  
    return rea;  
}  

线性:

ll p[max_];
ll prime[max_];
bool vis[max_];
ll pre[max_];
int pl=0;
void getphi()
{
	p[1]=1;
	for(int i=2;i<max_;i++)
	{
		if(vis[i]==false)
		{
			prime[++pl]=i;
			p[i]=i-1;
		}
		for(int j=1;j<=pl&&i*prime[j]<max_;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				p[i*prime[j]]=p[i]*prime[j];
				break;
			}
			else
			p[i*prime[j]]=p[i]*p[prime[j]];
		}
	}
}

6.广义斐波那契数列的循环节

F[n]=AF[N-1]+BF[N-2]

c=F[1]

若c是mod的二次剩余 p-1

若c是mod的非二次剩余 (p-1)(p+1)

7.Miller-Rabin素数测试+PollardRho大整数分解

const int Times = 10;
const int N = 5500;
LL ct, cnt;
LL fac[N], num[N];
LL gcd(LL a, LL b)
{
	return b? gcd(b, a % b) : a;
}
LL multi(LL a, LL b, LL m)
{
    LL ans = 0;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = (ans + a) % m;
            b--;
        }
        b >>= 1;
        a = (a + a) % m;
    }
    return ans;
}
LL quick_mod(LL a, LL b, LL m)
{
    LL ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = multi(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi(a, a, m);
    }
    return ans;
}
bool Miller_Rabin(LL n)
{
    if(n == 2) return true;
    if(n < 2 || !(n & 1)) return false;
    LL m = n - 1;
    int k = 0;
    while((m & 1) == 0)
    {
        k++;
        m >>= 1;
    }
    for(int i=0; i<Times; i++)
    {
        LL a = rand() % (n - 1) + 1;
        LL x = quick_mod(a, m, n);
        LL y = 0;
        for(int j=0; j<k; j++)
        {
            y = multi(x, x, n);
            if(y == 1 && x != 1 && x != n - 1) return false;
            x = y;
        }
        if(y != 1) return false;
    }
    return true;
}
LL pollard_rho(LL n, LL c)
{
    LL i = 1, k = 2;
    LL x = rand() % (n - 1) + 1;
    LL y = x;
    while(true)
    {
        i++;
        x = (multi(x, x, n) + c) % n;
        LL d = gcd((y - x + n) % n, n);
        if(1 < d && d < n) return d;
        if(y == x) return n;
        if(i == k)
        {
            y = x;
            k <<= 1;
        }
    }
}
void find(LL n, int c)
{
    if(n == 1) return;
    if(Miller_Rabin(n))
    {
        fac[ct++] = n;
        return ;
    }
    LL p = n;
    LL k = c;
    while(p >= n) p = pollard_rho(p, c--);
    find(p, k);
    find(n / p, k);
}
int main()
{
    LL n;
    while(cin>>n)
    {
        ct = 0;
        find(n, 120);
        sort(fac, fac + ct);
        num[0] = 1;
        int k = 1;
        for(int i=1; i<ct; i++)
        {
            if(fac[i] == fac[i-1])
                ++num[k-1];
            else
            {
                num[k] = 1;
                fac[k++] = fac[i];
            }
        }
        cnt = k;
        for(int i=0; i<cnt; i++)
            cout<<fac[i]<<"^"<<num[i]<<" ";
        cout<<endl;
    }
    return 0;
}

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页