数学题代码模板

随我不断学习而持续更新

1、质数的判定

试除法判定质数(只用循环sqrt(n)次)

bool is_prime(int n){
   if(n < 2)return false;
   for(int i = 2;i <= n/i; i++)
      if(n%i == 0)return false;
   return true;
}

2、质因数的分解

输出的是质因子及其个数

void divide(int n)
{
    for(int i = 2;i <= n/i;i ++ )
        if(n % i == 0)
        {
            int s=0;
            while(n%i==0)
            {
                n/=i;
                s++;
            }
            printf("%d %d",i,s);
        }
    if(n>1) printf("%d %d",n,1);

}

3、质数筛(埃式筛)

利用布尔值判定,再利用桶排序记录合数

int prime[];
bool st[];
void get_primes(int n)
{
    for(int i = 2;i <= n;i ++ )
    {
        if(!st[i])
        {
            primes[cnt ++] = i;//记录质数
            for(int j = i + i;j <= n;j += i) st[j] = true;//记录合数
        }
    }
}

4、质数(线性筛)//未学会

const int N=10000010;

int primes[N],cnt;
bool st[N];

void get_primes(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]<=n/i;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }
    }
}

5、求约数

试除法求约数

vector<int> get_divisors(int n)
{
    vector<int>res;
    for(int i=1;i<=n/i;i++)
        if(n%i==0)
        {
            res.push_back(i);
            if(i!=n/i) res.push_back(n/i);
        }
    sort(res.begin(),res.end());
    return res;
}

6、约数个数

#include <bits/stdc++.h>

using namespace std;

const int mod=1e9+5;
int main()
{
    int n;
    cin>>n;

    unordered_map<int,int>primes;//存底数和指数
    while(n--)
    {
        int x;
        cin>>x;
        for(int i=2;i<=x;i++)
            while(x%i==0)
            {
                x/=i;
                primes[i]++;
            }
        if(x>1) primes[x]++;
    }
    long long res =1;
    for(auto prime : primes) res = res * (prime.second +1)%mod;//循环用公式
    //如果 N = p1^c1 * p2^c2 * ... *pk^ck
    //约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
    cout<<res<<endl;
    return 0;
}

7、合并果子

洛谷P1090

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,c,ans,x,y;
    priority_queue<int,vector<int>,greater<int> >vis;
    cin>>n;
    ans=0;
    for(int i=1;i<=n;i++)
    {
        cin>>c;
        vis.push(c);
    }
        while(vis.size()>1)
    {
        x=vis.top(); vis.pop();
        y=vis.top(); vis.pop();
        ans+=x+y;
        vis.push(x+y);//注意不能直接将ans入堆,ans是最后的总和,而入堆的只是堆前两个数之和
    }
    cout<<ans<<endl;
    vis.pop();
    return 0;
}

8、约数的和

#include <bits/stdc++.h>

using namespace std;

const int mod=1e9+5;
int main()
{
    int n;
    cin>>n;

    unordered_map<int,int>primes;
    while(n--)
    {
        int x;
        cin>>x;
        for(int i=2;i<=x;i++)
            while(x%i==0)
            {
                x/=i;
                primes[i]++;
            }
        if(x>1) primes[x]++;
    }//求解约数结束
    long long res =1;
    for(auto prime : primes)//遍历求和开始
    {
        int p=prime.first,a=prime.second;
        long long t=1;
        while(a--)
            t=(t*p+1)%mod;//题干要求,答案取模
        res =res * t % mod;
    }
    cout<<res<<endl;

    return 0;
}

9、求两个数的最大公约数

#include <bits/stdc++.h>

using namespace std;

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",gcd(a,b));
    }
    return 0;
}

10、快排模板

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

int n;
int q[N];

void quick_sort(int q[],int l,int r)
{
    if(l >= r) return;//递归中止条件
    int x=q[(l+r)/2],i=l-1,j=r+1;//最先取中间值为断点,i为左指针,j为右指针,因为在循环里先移动指针,所以i,j要多初始化一个单位
    while(i<j)
    {
        do i++;while(q[i]<x);//当找到断点左边不小于x的值时循环结束
        do j--;while(q[j]>x);//当找到断点右边不大于x的值时循环结束
        if(i<j) swap(q[i],q[j]);//交换两个值
    }
    quick_sort(q,l,j);//递归继续排序
    quick_sort(q,j+1,r);
}
int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);

    quick_sort(q,0,n-1);

    for(int i=0;i<n;i++) printf("%d ",q[i]);

    return 0;
}

11、归并排序 //未学会

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

int n;
int q[N],tmp[N];

void merge_sort(int q[],int l,int r)
{
    if(l >= r) return;

    int mid = (l + r)>> 1;

    merge_sort(q,l,mid)merge_sort(q,mid + 1,r);//谜一样的递归排序
    
    int k = 0,i = l,j = mid + 1;
    while(i <= mid && j <= r)
        if(q[i] <= q[j]) tmp[k ++ ]=q[i ++ ];
        else tmp[k ++ ]=q[j ++ ];
    while(i <= mid) tmp[k ++ ]=q[i ++];
    while(j <= r) tmp[k ++ ]=q[j ++];

    for(i =l,j=0;i<=r;i++,j++) q[i] = tmp[j];
}

int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);

    merge_sort(q,0,n-1);

    for(int i=0;i<n;i++) printf("%d ",q[i]);

    return 0;
}

12、整数二分

来源于Acwing算法基础课-基础算法(一)

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n,m;
int q[N];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0;i < n; i ++ ) scanf("%d",&q[i]);

    while(m--)
    {
        int x;
        scanf("%d",&x);

        int l = 0,r = n - 1;
        while(l<r)
        {
            int mid = l+r >>1;
            if(q[mid]>=x) r=mid;//向左逼近答案
            else l=mid+1;
        }

        if(q[l]!=x) cout<<"-1 -1"<<endl;
        else
        {
            cout<<l<<' ';

            int l=0,r=n-1;
            while(l<r)
            {
                int mid=l+r+1 >>1;//需要加一,防止边界问题死循环
                if(q[mid]<=x) l=mid;//向右逼近答案
                else r=mid -1;
            }
            cout<<l<<endl;
        }
    }

    return 0;
}

13、浮点数二分

求一个数的平方根

#include <bits/stdc++.h>

using namespace std;

int main()
{
    double x;
    cin>>x;

    double l = 0,r=x;
    while(r-l>1e-6)
    {
        double mid = (l+r)/2;
        if(mid*mid>=x) r=mid;
        else l=mid;
    }
    printf("%lf\n",l);
    return 0;
}

14、高精度模板

模拟计算的过程
将数据存到数组里
加法:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

vector<int> add(vector<int> &A,vector<int> &B)
{
    vector<int>C;

    int t=0;
    for(int i=0;i<A.size()||i<B.size();i++)
    {
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        C.push_back(t%10);
        t/=10;
    }

    if(t) C.push_back(1);
    return C;
}

int main()
{
    string a,b;
    vector<int>A,B;

    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');

    auto C = add(A,B);

    for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
    return 0;
}

减法:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;

bool cmp(vector<int> &A,vector<int> &B)
{
    if(A.size()!=B.size()) return A.size() > B.size();
    for(int i=A.size()-1;i>=0;i--)
        if(A[i] != B[i])
            return A[i] > B[i];
    return true;
}
vector<int> sub(vector<int>&A,vector<int>&B)
{
    vector<int>C;
    for(int i = 0,t=0;i<A.size();i++)
    {
        t=A[i]-t;
        if(i<B.size()) t-=B[i];
        C.push_back((t+10)%10);
        if(t<0) t=1;
        else t=0;
    }
    while(C.size() > 1&& C.back() == 0) C.pop_back();
    return C;
}

int main()
{
    string a,b;
    vector<int>A,B;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');

    if(cmp(A,B))
    {
        auto C = sub(A,B);
        for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
    }
    else
    {
        auto C = sub(A,B);
        printf("-");
        for(int i = C.size()- 1;i>=0;i--) printf("%d",C[i]);
    }
    return 0;
}

乘法:

#include <bits/stdc++.h>

using namespace std;

vector<int> mul(vector<int> &A,int b)
{
    vector<int>C;
    int t=0;
    for(int i = 0;i<A.size()||t;i++)
    {
        if(i<A.size()) t += A[i]*b;
        C.push_back(t%10);
        t/=10;
    }
    return C;
}

int main()
{
    string a;
    vector<int>A;
    int b;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');

    auto C = mul(A,b);

    for(int i=C.size() -1;i>=0;i--) printf("%d",C[i]);

    return 0;
}

除法:

#include <bits/stdc++.h>

using namespace std;

vector<int> div(vector<int> &A,int b,int &r)
{
    vector<int>C;
    r=0;
    for(int i= A.size()-1;i>=0;i--)
    {
        r=r*10+A[i];
        C.push_back(r/b);
        r%=b;
    }
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}
int main()
{
    string a;
    vector<int>A;
    int b;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    int r;
    auto C = div(A,b,r);
    for(int i=C.size() -1;i>=0;i--) printf("%d",C[i]);
    cout<<endl<<r<<endl;
    return 0;
}

15、前缀和

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n,m;
int a[N],s[N];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);

    for(int i=1;i<=n;i++) s[i] = s[i-1] + a[i];

    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",s[r] - s[l-1]);
    }
    return 0;
}

二维前缀和:

#include <bits/stdc++.h>

using namespace std;

const int N = 1010;

int n,m,q;
int a[N][N],s[N][N];

int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);

    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j] = s[i-1][j] + s[i][j -1]-s[i-1][j-1] +a[i][j];
    while(q--)
    {
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%d\n",s[x2][y2] - s[x1-1][y2] - s[x2][y1- 1]+s[x1-1][y1-1]);
    }
    return 0;
}

16、差分//未学会

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;

int n,m;
int a[N],b[N];

void insert(int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);

    for(int i=1;i<=n;i++) insert(i,i,a[i]);

    while(m--)
    {
        int l,r,c;
        scanf("%d%d%d",&l,&r,&c);
        insert(l,r,c);
    }
    for(int i=1;i<=n;i++) b[i] += b[i-1];

    for(int i=1;i<=n;i++) printf("%d",b[i]);

    return 0;
}

17、双指针算法

for(i=0,j=0;i<n;i++)
{
   while(j<i&&check(i,j))j++;
   //每道题目的具体逻辑
}

18、离散化//不太会

Acwing区间和

#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int>PII;

const int N = 300010;

int n,m;
int a[N],s[N];

vector<int> alls;
vector<PII> add,query;

int find(int x)//一个二分查找的过程
{
    int l=0,r=alls.size()-1;
    while(l<r)
    {
        int mid = l+r >> 1;
        if(alls[mid]>=x) r=mid;
        else l=mid + 1;
    }
    return r+1;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)//记录插入数据
    {
        int x,c;
        cin>>x>>c;
        add.push_back({x,c});
        alls.push_back(x);
    }
    for(int i=0;i<m;i++)//记录询问数据
    {
        int l,r;
        cin>>l>>r;
        query.push_back({l,r});
        
        alls.push_back(l);
        alls.push_back(r);
    }
    //去重
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    //处理插入
    for(auto item : add)
    {
        int x=find(item.first);
        a[x] += item.second;
    }
    //处理前缀和
    for(int i=1;i<=alls.size();i++) s[i] = s[i - 1]+a[i];
    //处理询问
    for(auto item : query)
    {
        int l = find(item.first),r = find(item.second);
        cout<<s[r] - s[l - 1]<<endl;
    }
    return 0;
}

19、单调栈

AcWing-单调栈

#include <iostream>

using namespace std;

const int N = 100010;

int n;
int stk[N],tt;

int main()
{
    scanf("%d",&n);

    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        while(tt && stk[tt]>=x) tt --;
        if(tt)printf("%d ",stk[tt]);
        else printf("-1");

        stk[++tt]=x;
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值