数论模板

下面这个博客里有一些神奇的模板:http://blog.sina.com.cn/s/blog_82462ac30100y17u.html

里面包含了线性的数论算法,可以在线性的时间内实现:

1.筛出素数

2.求出每个数包含的素数个数

3.求出每个数的因子个数

4.求出欧拉函数

5.求出约数和

我对数论的理解就只能理解到线性素数筛,但感觉那个素数筛要比自己平时写的短而且快太多了,在此存一下模板,方便以后打印,代码都是源自上面的博客的。

 

#pragma warning(disable:4996)

#include <iostream>

#include <cstring>

#include <string>

#include <vector>

#include <cstdio>

#include <algorithm>

#include <cmath>

#include <queue>

#include <map>

using namespace std;



#define maxn 100000

#define ll long long



int p[maxn + 50]; // 存的素数表

int tot;

int vis[maxn + 50]; // vis访问表



// 线性素数筛

void getPrime()

{

	memset(vis, 0, sizeof(vis));

	tot = 0;

	for (int i = 2; i <= maxn; i++){

		if (!vis[i]) p[tot++] = i;

		for (int j = 0; j < tot&&i*p[j] <= maxn; j++){

			vis[i*p[j]] = true;

			if (!(i%p[j])) break;

		}

	}

}



int cnt[maxn + 50];

// 获得每个数包含的素数因子

void getPrime2()

{

	memset(vis, 0, sizeof(vis));

	memset(cnt, 0, sizeof(cnt));

	tot = 0;

	for (int i = 2; i <= maxn; i++){

		if (!vis[i]) {

			p[tot++] = i;

			cnt[i] = 1;

		}

		for (int j = 0; j < tot&&i*p[j] <= maxn; j++){

			vis[i*p[j]] = true;

			cnt[i*p[j]] = cnt[i] + 1;

			if (!(i%p[j])) break;

		}

	}

}



int divv[maxn + 50];

// 线性求每个数包含的因子个数

void getPrime3()

{

	memset(vis, 0, sizeof(vis));

	memset(cnt, 0, sizeof(cnt));

	memset(divv, 0, sizeof(divv));

	tot = 0;



	// if we consider divv[1]=1,then it should be added

	// divv[1]=1

	for (int i = 2; i <= maxn; i++){

		if (!vis[i]) {

			p[tot++] = i;

			cnt[i] = 1;

			divv[i] = 2;

		}

		for (int j = 0; j < tot&&i*p[j] <= maxn; j++){

			vis[i*p[j]] = true;

			if (i%p[j] == 0){

				divv[i*p[j]] = divv[i] / (cnt[i] + 1)*(cnt[i] + 2);

				cnt[i*p[j]] = cnt[i] + 1;

				break;

			}

			else{

				cnt[i*p[j]] = 1;

				divv[i*p[j]] = divv[i] * divv[p[j]];

			}

		}

	}

}



int phi[maxn + 50];

void getPrime4()

{

	memset(phi, 0, sizeof(phi));

	memset(vis, 0, sizeof(vis));

	tot = 0;

	for (int i = 2; i <= maxn; i++){

		if (!vis[i]){

			p[tot++] = i;

			phi[i] = i - 1;

		}

		for (int j = 0; j < tot&&i*p[j] <= maxn; j++){

			vis[i*p[j]] = true;

			if (i%p[j] == 0){

				phi[i*p[j]] = phi[i] * p[j];

				break;

			}

			else phi[i*p[j]] = phi[i] * (p[j] - 1);

		}

	}

}





int mnp[maxn + 50]; // minimal prime factor

ll dsum[maxn + 50]; // divisor sum



// 求约数和dsum

void getPrime5()

{

	memset(vis, 0, sizeof(vis)); 

	tot = 0;

	for (int i = 2; i <= maxn; i++){

		if (!vis[i]) {

			p[tot++] = i;

			mnp[i] = i;

		}

		for (int j = 0; j < tot&&i*p[j] <= maxn; j++){

			vis[i*p[j]] = true;

			mnp[i*p[j]] = p[j];

			if (!(i%p[j])) break;

		}

	}

	// i=p1^a1*p2^a2...pn^an

	// dsum[i]=(1+p1+..p1^a1)*(1+p2+..p2^a2).....

	dsum[1] = 1; int t0;

	for (int i = 2; i <= maxn; i++){

		t0 = 1;

		for (int j = i; j%mnp[i] == 0; j /= mnp[i]) t0 *= mnp[i];

		if (i != t0) dsum[i] = dsum[t0] * dsum[i / t0];

		else dsum[i] = (1LL * t0*mnp[i] - 1) / (mnp[i] - 1);

	}

}





int main()

{

	



}

 

你可能感兴趣的:(模板)