寒假Day1

寒假 Day 1

标签(空格分隔): 未分类


一、树状数组Bit
1.红色的幻想乡
是一道树状数组的题,主要考察对于树状数组的深度理解。
树状数组主要运用于单点修改和区间查询
这道题的难在于处理二维的矩阵中的bit。
!!放过的行数×行长度+放过的列数×列长度-抵消块数
横竖两个树状数组进行维护

二、关于RMQ
RMQ是一种集二分递推和动态规划思想于一身的诡异算法。
RMQ主要用于查询区间最大最小值,ps :同样可以考虑用线段树解决
RMQ是最大最小值的最好伙伴!!!
1.忠诚(RMQ板子题)

#include<bits/stdc++.h>
using namespace std;
int a[100001],Fmin[100002][30],n,m;
void STmin(){
    int k=log(n)/log(2);
    for(int i=1;i<=n;i++)
        Fmin[i][0]=a[i];
    for(int j=1;j<=k;j++)
        for(int i=1;(i+(1<<j)-1)<=n;i++) 
             Fmin[i][j]=min(Fmin[i][j-1],Fmin[i+(1<<(j-1))][j-1]);
} 
int RMQmin(int L,int R){
    int k=log(R-L+1)/log(2);
    return min(Fmin[L][k],Fmin[R-(1<<k)+1][k]); 
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    STmin();
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        cout<<RMQmin(x,y)<<" ";
    }
    return 0;
}

三、矩阵的运算
矩阵乘法的基础
简单的说矩阵就是二维数组,数存在里面,矩阵乘法的规则:A*B=C
其中c[i][j]为A的第i行与B的第j列对应乘积的和,即:
http://www.cnblogs.com/hadilo/p/5865541.html理解
(1)矩阵快速幂
主要通过把数放到矩阵的不同位置,然后把普通递推式变成”矩阵的等比数列”,最后快速幂求解递推式:
通过把原本的递推式转化成矩阵乘法,再用矩阵快速幂求解。
第一步先要列出递推式
第二步是建立矩阵递推式,找到转移矩阵
建立矩阵递推式的基本方法:
一般An与A(n-1)都是按照原始递推式来构建的,当然可以先猜一个An,主要是利用矩阵乘法凑出矩阵T,第一行一般就是递推式,后面的行就是不需要的项就让与其的相乘系数为0。矩阵T就叫做转移矩阵(一定要是常数矩阵),它能把A(n-1)转移到A(n);然后这就是个等比数列,直接写出通项:此处A1叫初始矩阵。所以用一下矩阵快速幂然后乘上初始矩阵就能得到An,这里An就两个元素(两个位置),根据自己设置的A(n)对应位置就是对应的值。
我明白啦哈哈哈哈哈
1.斐伯纳契数列
2.Matrix Power Series巨火题!
如果说Fibonacci考察的主要是数数之前连接而成的矩阵乘法快速幂
那么MPS考察的就是矩阵与矩阵之间构造递推式。
两个具有特殊性质的矩阵
零矩阵(全都是0)乘任何矩阵是零矩阵;
单位矩阵(对角线都是1)乘任何矩阵都是原矩阵本身
贴上一份矩阵快速幂的板子

#include<cstdio>
#include<iostream>
using namespace std;
const int mod=1e9+7;
#define LL long long
LL n,k;
struct Matrix{
    LL s[202][202];
}A,B,blank;
inline Matrix operator * (Matrix a,Matrix b)
{
    Matrix now=blank;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                now.s[i][j]=(now.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod;
    return now;
}
inline void Fast_pow(Matrix a,LL b)
{
    for(int i=0;i<n;i++)B.s[i][i]=1;
    while(b)
    {
        if(b&1)B=B*a;
        a=a*a;
        b>>=1;
    }
}
int main()
{
    scanf("%lld%lld",&n,&k);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            scanf("%lld",&A.s[i][j]);
    Fast_pow(A,k);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)printf("%lld ",B.s[i][j]);
        putchar('\n');
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值