简单数论总结

一.最长子序列问题,见http://blog.csdn.net/qq_37416823/article/details/77718585

二·放苹果问题
【问题描述】将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5; 1,5,1; 5,1,1;
问有多少种不同的分法。
【分析】根据排列组合公式得,将整数n分成k份相当于Σn-i分成k-1份(1<=i<=N/K)
核心代码为:

int dfs(int sum,int step,int now)  //sum为n,step为k,now是防止重复的
{  
    int g=0;  
    if(step==1) return g=1;//边界条件  
    for(int i=now;i<=sum/step;i++)//从now枚举,防止重复  
        g+=dfs(sum-i,step-1,i);//统计方案和  
    return g;  
}  

三.最大子段和问题
【题目描述】给出一段序列,选出其中连续且非空的一段使得这段和最大
【分析】使用滚动数组来解决这道题目,我们注意到,a[i]=max(a[i-1],sum);
也就是a[i]的值与a[i-2],a[i-3],a[i-4]……已经没有关系了。
【核心代码】

 sum=a[1];  
    for(int i=2;i<=n;++i) {  
        scanf("%d",&a[i%2]);  
        sum+=a[i%2];  
        a[i%2]=max(a[(i-1)%2],sum);  
        if(sum<0) sum=0;  
    }  

四.逆序对
【问题描述】对于给定的一段正整数序列,逆序对就是序列中ai>aj且i

inline void add(int i,int x){//树状数组添加数   
    while(i<=n){  
        tree[i]+=x;  
        i+=i&-i;  
    }  
}  
inline int quary(int i){//查询个数   
    int s=0;  
    while(i){  
        s+=tree[i];  
        i-=i&-i;  
    }  
    return s;  
}  

排序和查询添加的核心代码

 sort(p+1,p+1+n,cmp);  
    for(int i=1;i<=n;i++)  
        a[p[i]]=i;//p[i]变不了,重新编号   
    for(int i=1;i<=n;i++){  
        ans+=i-1-quary(a[i]);    //当前树状数组中有**i-1**个(为什么?),quary(a[i])前缀和查出a[i]前的个数  
        add(a[i],1);                    //值为a[i]的数又增加了一个  
    }  

五.最大公约数和最小公倍数问题
最大公约数核心代码

int gcd(int a,int b){  
    if(b==0) return a;  
    return gcd(b,a%b);  
}  

最小公倍数=两整数的乘积÷最大公约数

六.快速幂
核心代码:

long long qpow(long long n,long long x,long long mod)  
{  
    if(x==0) return 1;//递归出口:0次方为1  
    long long res=qpow(n*n%mod,x/2,mod);//递归  
    if(x&1) res=res*n%mod;//若x为奇数那么把返回值乘上n  
    return res;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值