zoukankan      html  css  js  c++  java
  • 数论模板

    下面这个博客里有一些神奇的模板: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()
    {
    	
    
    }
    
  • 相关阅读:
    Sqlserver 实际开发中表变量的用法
    Python Day 20 面向对象 (面向对象的组合用法,面向对象的三大特性
    Python Day 19 面向对象(初识面向对象)
    Python Day 18 常用模块(模块和包)
    Python Day 17 常用模块(常用模块一 时间模块,random模块,os模块,sys模块,序列化模块)
    Python Day 15 函数(递归函数、二分查找算法)
    Python Day 14 函数(内置函数,匿名函数(lambda表达式))
    Python Day 13 函数(迭代器,生成器,列表推导式,生成器表达式)
    Python Day 11 + Python Day 12 函数(函数名的应用,闭包,装饰器)
    Python Day 10 函数(名称空间,作用域,作用域链,加载顺序等; 函数的嵌套 global,nonlocal)
  • 原文地址:https://www.cnblogs.com/chanme/p/3851475.html
Copyright © 2011-2022 走看看