数论模板

下面这个博客里有一些神奇的模板: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()
{
	

}

 

posted @ 2014-07-17 16:46  chanme  阅读(185)  评论(0编辑  收藏  举报