数论板子

数论板子

数论分块 :

        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;
}

原文地址:https://www.cnblogs.com/Hs-black/p/11626119.html

时间: 2024-10-09 20:43:53

数论板子的相关文章

数论板子大总结

在这里,将有我迄今为止学过的所有数论. 1.素数筛--埃拉托斯特尼筛法 时间复杂度:O(nloglogn) 方法:用每个素数筛所有它的倍数 证明:略 for (int i=2;i<=N;i++) is[i]=1; for (int i=2;i<=N;i++) if (is[i]) for (int j=i*i;j<=2000;j+=i) is[j]=0; 2.素数筛--欧拉筛法 时间复杂度:O(n) 方法&证明:埃拉托斯特尼对于每个合数筛了很多遍,而欧拉对于每个合数只被自己的最小

Codeforces 1106F Lunar New Year and a Recursive Sequence (数学、线性代数、线性递推、数论、BSGS、扩展欧几里得算法)

哎呀大水题..我写了一个多小时..好没救啊.. 数论板子X合一? 注意: 本文中变量名称区分大小写. 题意: 给一个\(n\)阶递推序列\(f_k=\prod^{n}_{i=1} f_{k-i}b_i\mod P\)其中\(P=998244353\), 输入\(b_1,b_2,...,b_n\)以及已知\(f_1,f_2,...,f_{n-1}=1\), 再给定一个数\(m\)和第\(m\)项的值\(f_m\), 求出一个合法的\(f_n\)值使得按照这个值递推出来的序列满足第\(m\)项的值为

一些数论的板子

1.线性筛逆元 1 for(ll i=2;i<=n;i++) 2 inv[i]=(mod-mod/i)*inv[mod%i]%mod; 原文地址:https://www.cnblogs.com/guapisolo/p/9744617.html

1200 同余方程[一中数论随堂练]

1200 同余方程 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 求关于 x 同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入描述 Input Description 输入只有一行,包含两个正整数 a, b,用 一个 空格隔开. 输出描述 Output Description 输出只有一行包含一个正整数x0,即最小正整数解,输入数据保证一定有解. 样例输入

你好 数论(未完待续)

据说每年noip都会考数论的题?! 蒟蒻表示智商不够,被数论完虐..... 所以我就只能在这里整理整理各种数论的板子了.... 一.素数 http://www.cnblogs.com/mycapple/archive/2012/08/07/2626898.html 1.欧拉筛(线性筛) int Euler_sieve() { memset(not_prime,0,sizeof(not_prime)); for(int i=2;i<=n;i++) { if(!not_prime[i]) prime

18寒假的数论

1.容斥原理找1到M中与N互质的数 int primes[33], ptot; vector<pair<int,int> > split(int n) { vector<pair<int,int> > stk; for(int i = 2; i * i <= n; i++) { if(n % i == 0) { stk.push_back(make_pair(i, 0));//一维表示因子,二维表示个数 while(n % i == 0) { n /=

Noip前的大抱佛脚----数论

数论 知识点 Exgcd \(O(logn)\)求解\(Ax+By=C\)的问题 1.若\(C\%gcd(A,B)!=0\)则无解 2.\(Gcd=gcd(A,B);A/=Gcd,B/=Gcd,C/=Gcd\) 3.代入下面代码求\(Ax+By=1\) 4.\(x*C\),得到一组特解 5.通解为\(\begin{cases}x=x_0+k*B \\y=y_0+k*A\end{cases}\) void Exgcd(ll a,ll b,ll &x,ll &y) { if(!b){x=1;y

NKOJ1236 a^b (数论定理的应用)

          a^b 对于任意两个正整数a,b(0<=a,b<10000)计算a b各位数字的和的各位数字的和的各位数字的和的各位数字的和. Input 输入有多组数据,每组只有一行,包含两个正整数a,b.最后一组a=0,b=0表示输入结束,不需要处理. Output 对于每组输入数据,输出ab各位数字的和的各位数字的和的各位数字的和的各位数字的和. Sample Input 2 3 5 7 0 0 Sample Output 8 5 思路: 数论定理:任何数除以9的余数等于各位数的和除

CodeForces 396A 数论 组合数学

题目:http://codeforces.com/contest/396/problem/A 好久没做数论的东西了,一个获取素数的预处理跟素因子分解写错了,哭瞎了,呵呵, 首先ai最大值为10^9,n为500,最坏的情况 m最大值为500个10^9相乘,肯定不能获取m了,首选每一个ai肯定是m的一个因子,然后能分解就把ai给分解素因子,这样全部的ai都分解了  就能得到m的 所有素因子 以及 所有素因子的个数,题目求的 是n个因子的 不同序列的个数,所以每次 只能选出n个因子,这n个因子由素因子