数论板子

Posted hs-black

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论板子相关的知识,希望对你有一定的参考价值。

数论板子

数论分块 :

        j = n / (n / i);
        ans += (n/i) * (j - i + 1);

筛法:

线性筛:

#include<cstring>
#incldue<cmath>
const int MAXN=1000010;
bool prime[MAXN];
int Prime[MAXN];
int num=0;
void make_prime()

    memset(prime,true,sizeof(prime));
    prime[0]=prime[1]=false;
    for(int i=2;i<=MAXN;i++)
    
        if(prime[i])
        
            Prime[num++]=i;
        
        for(int j=0;j<num&&i*Prime[j]<MAXN;j++)
        
            prime[i*Prime[j]]=false;
            if(!(i%Prime[j]))
                break;
        
    
    return;

杜教筛:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<tr1/unordered_map>
using namespace std;
using namespace std::tr1;
int read(void) 
    int x = 0;
    char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) 
        x = (x << 3) + (x << 1) + c - '0';
        c = getchar();
    
    return x;

int T, n;
#define ll long long
const int N = 7000005;
ll sum_phi[N];
int sum_mu[N];
int prime[2000005];
bool vis[N];
int tot;
int maxn = 7000000;
void pre(void) 
    sum_phi[1] = sum_mu[1] = 1;
    for (int i = 2;i <= maxn; i++) 
        if (!vis[i]) 
            prime[++tot] = i;
            sum_phi[i] = i - 1;
            sum_mu[i] = -1;
        
        for (int j = 1;j <= tot && prime[j] * i <= maxn; j++) 
            int tmp = i * prime[j];
            vis[tmp] = 1;
            if (i % prime[j]) 
                sum_phi[tmp] = sum_phi[i] * (prime[j] - 1);
                sum_mu[tmp] = -sum_mu[i];
            
            else 
                sum_phi[tmp] = sum_phi[i] * prime[j];
                break;
            
        
    
    for (int i = 2;i <= maxn; i++) 
    sum_phi[i] += sum_phi[i-1], 
    sum_mu[i] += sum_mu[i-1];

unordered_map<int,ll> f_mu, f_phi;
ll phi(int x) 
    if (x <= maxn) return sum_phi[x];
    if (f_phi[x]) return f_phi[x];
    ll ans = (1 + (ll)x) * (ll)x / 2;
    int p;
    for (int l = 2, r;l <= x; l = r + 1) 
        p = x / l;
        r = x / p;
        ans -= (r - l + 1) * phi(p);
    
    return f_phi[x] = ans;

    
int mu(int x) 
    if (x <= maxn) return sum_mu[x];
    if (f_mu[x]) return f_mu[x];
    int ans = 1;
    int p;
    for (int l = 2, r;l <= x; l = r + 1) 
        r = x / (p = x / l);
        ans -= (r - l + 1) * mu(p);
    
    return f_mu[x] = ans;

int main() 
    pre();
    T = read();
    while (T--) 
        n = read();
        printf ("%lld %d\n", phi(n), mu(n));
    
    return 0;

拓展欧几里得:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int x, y, a, b;
void gcd(int m,int n) 
    int k = m / n, p = m % n;
    if (p == 1) 
        x = -k, y = 1;
        return;
    
    gcd(n, p);
    int z = y;
    y = x,x = z - x * k;

int main() 
    scanf ("%d %d", &a, &b);
    gcd(a, b);
    cout << (y % b + b) % b;
    return 0;

乘法逆元(线性) :

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 3006000;
#define ll long long
ll inv[N];
int main() 
    int n, p; cin >> n; cin >> p;
    inv[1] = 1;
    cout << 1 << endl;
    for (int i = 2;i <= n; i++) 
        inv[i] = (p - (p / i)) * inv[p % i] % p;
        printf ("%lld\n", inv[i]);
    
    return 0;

快速幂(???) :

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long s;
long long a,k;
long long fuc(long long b)

    if(b==1) return a;
    if(b==0) return 1;
    long long h=fuc(b/2)%k;
    if(b%2==0) return h*h;
    else return h*h*a;

int main()

    long long b;
    cin>>a>>b>>k;
    cout<<a<<"^"<<b<<" mod "<<k<<"="<<fuc(b)%k;
    return 0;

以上是关于数论板子的主要内容,如果未能解决你的问题,请参考以下文章

数论板子大总结

板子数论集合

数论板子——来自Loi_black

ACM-数论-广义欧拉降幂

你好 数论(未完待续)

Codeforces 396A 数论,组合数学