ACM暑期集训2

今天主要学习了线性DP和背包问题以及快速幂。

1.整数快速幂:

这个直接粘上代码

int QPow(int x,int n)
{
    int res = x,ans = 1;
    while(n)
    {
        if(n&1)
        {
            ans = ans * res;
        }
        res = res*res;
        n = n>>1;
    }
    return ans;
}

2.矩阵快速幂:

主要就是将整数快速幂的乘法运算换做矩阵的乘法

下面的代码是方阵的快速幂

const int N=10;
int tmp[N][N];
void multi(int a[][N],int b[][N],int n)//n为方阵的大小
{
    memset(tmp,0,sizeof tmp);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        for(int k=0;k<n;k++)
        tmp[i][j]+=a[i][k]*b[k][j];
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        a[i][j]=tmp[i][j];
}
int e[N][N];
void Pow(int a[][N],int n)
{
    memset(e,0,sizeof e);//n是幂,N是矩阵大小
    for(int i=0;i<N;i++) e[i][i]=1;  //e[][]为单位矩阵
    while(n)
    {
        if(n&1)
            multi(e,a,N);
        multi(a,a,N);//a=a*a
        n>>=1;
    }
}

矩阵快速幂的一个重要应用就是求递推式,这个在这里不做延伸。

3.线性DP

最长不下降子序列的长度:
用dp[i]表示前i个元素的LIS

对于第i个元素,其所对应的长度应从前往后找,找到所有可以添加的子序列,并取其中的最大值,可知状态转移方程:
          dp[i]=max(dp[i],dp[j]+1); // j:由1到i

最大连续子段和:
用dp[i]表示以第i个元素为结尾的最大连续子段和

对于第i个元素,其dp[i-1] 已经最优,那么这个元素要么加上前面的最优,要么本身就是最优,可知状态转移方程:

dp[i]=max(a[i],dp[i-1]+a[i]);// 然后再遍历求出最大值即可

最长公共子序列:
假设两个子序列x[1~m],y[1~n] 且z[1~k]为它们的最长公共子序列,则有:
如果xm=yn,则zk=am=bn(只有这样子序列才最长),且z[1~k-1]是x[1~m-1]和y[1~n-1]的一个最长公共子序列;
如果xm!=yn,若zk!=xm,则z[1~k]是x[1~m-1]和y[1~n]的一个最长公共子序列;若zk!=bn,则z[1~k]是x[1~m]和y[1~n-1]的一个最长公共子序列。可知状态转移方程:

dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

 if(a[i]==b[j])         

{             

dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);

}

4.一些思想

1)先看这样一道题:

假设我们有一个序列S,我可以从中取出若干的数,并且这些序列还满足下面的条件:

1.取出负数的话,我不得钱

2.取出S[i]>=10000的数,我可以得到5块钱,并且我要把他变成 S[i] = S[i] – 10000

3.其余情况我只能得到一块钱

4.取出的数不能打乱原有的顺序

问我能不能选出这样一个子序列t,使得t中的元素都是不下降的,并且得到钱最多?

这是一个最长不下降子序列问题,对于大于一万的数怎么处理呢?

关键来了,可以将大于一万的数减去一万,然后将该数变为五个插入到当前数所在位置(这样处理,每个数的价值就是一,这个数只要选一个就可以选五个,价值就是五)

2)二维前缀和:

采用二阶矩阵来记录矩阵某一点(m,n)和(0,0)所在行列所围成的矩阵中所有数的和,扫一遍即可求出这个二阶矩阵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值