Leetcode刷题笔记27:202006-4 201604-1-2(矩阵快速幂 | 递推公式变换矩阵)

第二十三天 2021-4-6 备战CSP
刷题模块:CSP 202006-4

一、矩阵快速幂

教程文章通俗易懂,一应俱全:矩阵快速幂——入门

整数快速幂模板
int quickPow(int a,int n){   //快速幂
    int ans = 1;
    while(n){
        if(n&1) ans*=a;
        a *= a;
        n /= 2;
    }
    return ans;
}
矩阵快速幂模板
void Matrix(int (&a)[2][2],int b[2][2]){   //矩阵乘法
    int tmp[2][2] = {0};
    for(int i = 0; i < 2; ++i)
        for(int j = 0; j < 2; ++j)
            for(int k = 0; k < 2; ++k)
                tmp[i][j] = (tmp[i][j] + a[i][k] * b[k][j]) % N;  //矩阵相乘,注意mod
    for(int i = 0; i < 2; ++i)
        for(int j = 0; j < 2; ++j)  
            a[i][j] = tmp[i][j]; //赋值返回数据
}
//cot 结果数组,初始为单位矩阵
//temp底数数组,为幂的底数
void quickPow(){   //快速幂
    while(n){
       if(n & 1) Matrix(cot,temp);   //如果是奇数
       Matrix(temp,temp);   
       n /= 2;  //不断除2
	}
}

二、202006-4

202006-4 CCF CSP认证 1246(digits) 96分 动态规划

★:动态规划DP递推公式如何转为递推矩阵

有如下动态规划递推公式:

state[i][1]=state[i-1][2];
state[i][2]=state[i-1][3]+state[i-1][4];
state[i][3]=state[i-1][1];
state[i][4]=state[i-1][1]+state[i-1][2];

则可以得出递推矩阵:
在这里插入图片描述
已知初始状态S、递推关系矩阵A以及他们的递推关系:
在这里插入图片描述
则可以得出任意状态的值,其中关系矩阵A的i次方由矩阵快速幂计算:
在这里插入图片描述

三、201604-1

Debug点:

注意unsigned int的使用,若进行了两个整数的减法,并可能结果为负数,则不能使用unsigned int。

#include<iostream>
#include<cstdio>
using namespace std;

int n;
int sumDay, d1, d2;
bool flag;

int main(){
    sumDay = 0;
    flag = true;

    scanf("%d", &n);
    if(n == 1){
        scanf("%d", &d1);
        n--;
    }
    else {
        scanf("%d %d", &d1, &d2);
        flag = (d2 - d1) > 0;
        n = n - 2;
    }

    while(n--) {
        d1 = d2;
        scanf("%d", &d2);
        if((d2 - d1) > 0){
            if(!flag) sumDay++;
            flag = true;
        }
        else{
            if(flag) sumDay++;
            flag = false;
        }
    }

    printf("%d\n", sumDay);
    return 0;
}

四、201604-2

写了很长时间,逻辑思维还有点混乱,但是没想到竟然一遍过了

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

bool arr[20][15];
bool block[4][4];
int arrTop[10],blockBottom[4];
int pos;

void init(){
    for(int i=0;i<10;i++){
        arrTop[i]=15;
    }
    for(int i=0;i<4;i++){
        blockBottom[i]=-15;
    }
}
int main() {
    freopen("in.txt","r",stdin);
    init();

    for(int i = 0; i < 15; i++) {
        for(int j = 0; j < 10; j++) {
            scanf("%d", &arr[i][j]);
            if(arr[i][j] && i < arrTop[j]){
                arrTop[j] = i;
            }
        }
    }
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++){
            scanf("%d", &block[i][j]);
            if(block[i][j] && i > blockBottom[j]){
                blockBottom[j] = i;
            }
        }
    }
    scanf("%d", &pos);

    int contactDis = 15, contactCol=0;
    for(int b = 0, a = pos-1; b < 4; b++, a++){
        if(arrTop[a] - blockBottom[b] < contactDis){
            contactDis = arrTop[a] - blockBottom[b];
            contactCol = b;
        }
    }
	
	int bottomCol=0;
	for(int i=0;i<4;i++){
		bottomCol=max(bottomCol,blockBottom[i]);
	}
    int contactPos = arrTop[contactCol+pos-1]-blockBottom[contactCol]-1;
    for(int bi = 0, ai = contactPos; bi <= bottomCol; bi++, ai++) {
        for(int bj = 0, aj = pos - 1; bj < 4; bj++, aj++) {
        	if(!arr[ai][aj] && block[bi][bj]){
        		arr[ai][aj] = block[bi][bj];
        	}
        }
    }

    for(int i = 0; i < 15; i++) {
        for(int j = 0; j < 10; j++) {
            printf("%d", arr[i][j]);
            if(j != 9) printf(" ");
        }
        printf("\n");
    }
    


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值