• 数论模板


    下面这个博客里有一些神奇的模板: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()
    {
    	
    
    }
    
  • 相关阅读:
    为mongoDB加用户权限管理
    手机号归属地查询接口
    关于微信小程序
    linux交互执行命令,expect
    apache配置跨域请求代理
    Linux(Mac)常用命令
    解决:配置虚拟主机,重启apache,[warn] _default_ VirtualHost overlap on port 80, the first has precedence
    linux下grep分析apache日志的命令集合
    解决Macbook Pro蓝牙不可用问题
    Apache如何开启Gzip压缩
  • 原文地址:https://www.cnblogs.com/chanme/p/3851475.html
Copyright © 2020-2023  润新知