矩阵快速幂专题 HDU1757 HDU1575 HDU2604 HDU2256 CF185A HDU2276 HDU2842

HDU1757
递推式给了,入门裸题。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
LL k ;
int m ;
int b[15];
struct Matrix{
    LL a[12][12];
};
Matrix Mul( Matrix x , Matrix y ){
    Matrix res ;
    memset( res.a , 0 , sizeof(res.a) );
    for( int i = 0 ; i < 10 ; i++ ){
        for( int j = 0 ; j < 10 ; j++ ){
            for( int k = 0 ; k < 10; k++ ){
                res.a[i][j] = ( res.a[i][j] + x.a[i][k] * y.a[k][j] % m ) % m;
            }
        }
    }   
    return res ;
}

Matrix quick( Matrix x , int b ){
    Matrix ans ;
    memset( ans.a , 0 , sizeof(ans.a) );
    for( int i = 0 ; i < 10 ; i++ ) ans.a[i][i] = 1 ;
    while( b ){
        if( b & 1 ){
            ans = Mul( ans , x );
        }
        b >>= 1 ;
        x = Mul( x , x ) ;
    }
    return ans ;
}

int main(){
    while( ~scanf("%lld%d",&k,&m) ){
        if( k < 10 ){
            printf("%d\n",k%m);
            continue ; 
        }
        Matrix mat ;
        memset( mat.a , 0 , sizeof(mat.a) );
        for( int i = 0 ; i < 10 ; i++ ){
            scanf("%d",&mat.a[0][i]);
        }
        for( int i = 1 ; i < 10 ; i++ ){
            mat.a[i][i-1] = 1;
        }
        Matrix s = quick( mat , k - 9 );

        Matrix ans ;
        memset( ans.a , 0 , sizeof(ans.a) );
        for( int i = 0 ; i < 10 ; i++ ) ans.a[i][0] = 9 - i ; 

        LL res = 0;
        for( int i = 0 ; i < 10 ; i++ ){
            res = ( res + s.a[0][i] * ans.a[i][0] ) % m;
        }
        printf("%d\n",res);
    }
    return 0 ;
}

HDU1575
更裸。。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int MOD = 9973 ;
struct Matrix{
    LL a[12][12];
};
int n , k ;
Matrix Mul( Matrix x , Matrix y ){
    Matrix ans ;
    memset( ans.a , 0 , sizeof(ans.a) );
    for( int i = 0 ; i < n ; i++ ){
        for( int j = 0 ; j < n ; j++ ){
            for( int k = 0 ; k < n ; k++ ){
                ans.a[i][j] = ( ans.a[i][j] + x.a[i][k] * y.a[k][j] % MOD ) % MOD;
            }
        }
    }
    return ans ;
}

Matrix quick( Matrix a , int b ){
    Matrix ans ;
    memset( ans.a , 0 ,sizeof(ans.a) );
    for( int i = 0 ; i < n ; i++ ) ans.a[i][i] = 1 ;    
    while( b ){
        if( b & 1 ) ans = Mul( ans , a );
        b >>= 1 ;
        a = Mul( a , a );
    } 
    return ans ;
}

int main(){
    int T;
    scanf("%d",&T);
    while( T-- ){
        scanf("%d%d",&n,&k);
        Matrix Mat; 
        memset( Mat.a , 0 , sizeof(Mat.a) );
        for( int i = 0 ; i < n ; i++ ){
            for( int j = 0 ; j < n ; j++ ){
                scanf("%d",&Mat.a[i][j]);
            }
        }
        Matrix res = quick( Mat , k ) ;
        int ans = 0 ;
        for( int i = 0 ; i < n ; i++ ){
            ans = ( ans + res.a[i][i] ) % MOD ;
        }
        printf("%d\n",ans);
    }   
    return 0 ;
}

HDU2604
题意:对于只由数字1和0构成的字符串,给出长度为n的,不含子串101且不含子串111的字符串的个数对m取模的值。
推公式:f[n] 为满足条件的长度n的串的个数
如果最后一个为0,那么结果就是f(n-1) 后面加0,肯定不会出现101,111
如果最后一个为1,还要考虑前面2位必须为00 (f[n-3]), 01(前面必须为0)所以就是f[n-4]
得到:f[n] = f [n-1] + f[n-3] + f[n-4]

Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
int n , m ;
struct Matrix{
    int a[4][4];
};

Matrix Mul( Matrix x , Matrix y ){
    Matrix ans ;
    memset( ans.a , 0 , sizeof(ans) );
    for( int i = 0 ; i < 4 ; i++ ){
        for( int j = 0 ; j < 4 ; j++ ){
            for( int k = 0 ; k < 4 ; k++ ){
                ans.a[i][j] = ( ans.a[i][j] + x.a[i][k] * y.a[k][j] % m ) % m ;
            }
        }
    }
    return ans ;
}

Matrix quick( Matrix x , int b ){
    Matrix ans;
    memset( ans.a , 0 , sizeof(ans) );
    for( int i = 0 ; i < 4 ; i++ ) ans.a[i][i] = 1 ;
        while( b ){
            if( b & 1 ) ans = Mul( ans , x );
            x = Mul(x,x);
            b >>= 1 ;
        }
        return ans ;
    }

    int main(){
        while( ~scanf("%d%d",&n,&m) ){
            if( n == 0 )      printf("0\n");
            else if( n == 1 ) printf("%d\n",2%m);
            else if( n == 2 ) printf("%d\n",4%m);
            else if( n == 3 ) printf("%d\n",6%m);
            else if( n == 4 ) printf("%d\n",9%m);
            else{
                Matrix ans ;
                memset( ans.a , 0 , sizeof(ans.a) );
                ans.a[0][0] = 1 ; ans.a[0][1] = 0 ; ans.a[0][2] = 1 ; ans.a[0][3] = 1 ;
                ans.a[1][0] = 1 ; ans.a[1][1] = 0 ; ans.a[1][2] = 0 ; ans.a[1][3] = 0 ;
                ans.a[2][0] = 0 ; ans.a[2][1] = 1 ; ans.a[2][2] = 0 ; ans.a[2][3] = 0 ;
                ans.a[3][0] = 0 ; ans.a[3][1] = 0 ; ans.a[3][2] = 1 ; ans.a[3][3] = 0 ;
                Matrix tmp ;
                memset( tmp.a , 0 ,sizeof(tmp.a) );
                tmp.a[0][0] = 9 ; tmp.a[1][0] = 6; tmp.a[2][0] = 4 ; tmp.a[3][0] = 2;
                Matrix t = quick( ans , n - 4 );
                int res = 0 ;
                for( int i = 0 ; i < 4 ; i++ ){
                    res = ( res + t.a[0][i] * tmp.a[i][0] ) % m ;
                }
                printf("%d\n",res);
            }
        }
        return 0 ;
    }

HDU2256

思路:
这里写图片描述
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int MOD = 1024 ;
struct Matrix{
    int a[3][3];
};
int n ;
Matrix Mul( Matrix x , Matrix y ){
    Matrix ans ;
    memset( ans.a , 0 , sizeof(ans.a) );
    for( int i = 0 ; i < 2 ; i++ ){
        for( int j = 0 ; j < 2 ; j++ ){
            for( int k = 0 ; k < 2 ; k++ ){
                ans.a[i][j] = ( ans.a[i][j] + x.a[i][k] * y.a[k][j] % MOD ) % MOD;
            }
        }
    }
    return ans ;
}

Matrix quick( Matrix a , int b ){
    Matrix ans ;
    memset( ans.a , 0 ,sizeof(ans.a) );
    for( int i = 0 ; i < 2 ; i++ ) ans.a[i][i] = 1 ;    
        while( b ){
            if( b & 1 ) ans = Mul( ans , a );
            b >>= 1 ;
            a = Mul( a , a );
        } 
        return ans ;
    }

    int main(){
        int T;
        scanf("%d",&T);
        while( T-- ){
            scanf("%d",&n);
            Matrix Mat ;
            Mat.a[0][0] = 5 ; Mat.a[0][1] = 12;
            Mat.a[1][0] = 2 ; Mat.a[1][1] = 5;
            Matrix ans = quick( Mat , n - 1 );
            int A1 = 5 ;
            int B1 = 2 ;
            int An = ( 5 * ans.a[0][0] + 2 * ans.a[0][1] )  % MOD;
            printf("%d\n",(An*2-1+MOD)%MOD);
        }   
        return 0 ;
    }

CF185A
公式:F(n上) = 2F(n-1上) + 4 ^(n-2)
推导:F(n上) = F(n-1下) + 3 * F(n-1上)
F(n-1 下) + F (n - 1上) = F (n-1)
上面两个式子可以得出F(n上) = F(n-1) + 2*F(n-1上)
所以F(n上) = 4^(n-2) + 2 * F(n-1上)
其中,上下表示上三角下三角,没有上下的为其总和。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const LL MOD = 1e9+7;
struct Matrix{
    LL a[4][4];
};

Matrix Mul( Matrix x , Matrix y ){
    Matrix res ;
    memset( res.a , 0 , sizeof(res.a) );
    for( int i = 0 ; i < 3 ; i++ ){
        for( int k = 0 ; k < 3 ; k++ ){
            if( x.a[i][k] ){
                for( int j = 0 ; j < 3 ; j++ ){
                    if( y.a[k][j] )
                        res.a[i][j] = ( res.a[i][j] + x.a[i][k] * y.a[k][j] ) % MOD;
                }
            }
        }
    }
    return res ;
}

Matrix quick( Matrix a , LL b ){
    Matrix res ; 
    memset( res.a , 0 , sizeof(res.a) );
    for( int i = 0 ; i < 3 ; i++ ) res.a[i][i] = 1 ;
        while( b ){
            if( b & 1 ){
                res = Mul( res , a );
            }
            b >>= 1;
            a = Mul( a , a );
        }
        return res ; 
    }

    int main(){
        LL n ;
        scanf("%I64d",&n);
        if( !n ) printf("1\n");
        else if( n == 1 ) printf("3\n");
        else{
            Matrix Mat ;
            Mat.a[0][0] = 2 ; Mat.a[0][1] = 0 ; Mat.a[0][2] = 4;
            Mat.a[1][0] = 1 ; Mat.a[1][1] = 0 ; Mat.a[1][2] = 0;
            Mat.a[2][0] = 0 ; Mat.a[2][1] = 0 ; Mat.a[2][2] = 4;
            Matrix ans;
            ans.a[0][0] = 3 ; ans.a[1][0] = 1 ; ans.a[2][0] = 1 ;
            Matrix tmp = quick( Mat , n - 1 );
            LL res = 0 ;
            for( int i = 0 ; i < 3 ; i++ ){
                res = ( res + tmp.a[0][i] * ans.a[i][0] % MOD ) % MOD;
            }
            printf("%I64d\n",res);
        }
        return 0 ;
    }

HDU2276
题意:每次操作如果i-1是1就将i反转(1变0,0变1),0的位置看n-1
思路:构造的矩阵是n*n的,除了第一列是0和n-1位置为1外,其他每列都是i和i-1位置为1.
m次方,对2取余。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 1e2+6;
char s[AX];
int val[AX];
int m , n ; 

struct Matrix{
    int a[AX][AX];
};

Matrix Mul( Matrix x , Matrix y ){
    Matrix res ;
    memset( res.a , 0 , sizeof(res.a) );
    for( int i = 0 ; i < n ; i++ ){
        for( int j = 0 ; j < n ; j++ ){
            for( int k = 0 ; k < n ; k++ ){
                res.a[i][j] = ( res.a[i][j] + x.a[i][k] * y.a[k][j] % 2 ) % 2 ;
            }
        }
    }
    return res ;
}

Matrix quick( Matrix a , int b ){
    Matrix res ;
    memset( res.a , 0 , sizeof(res.a) ) ;
    for( int i = 0 ; i < n ; i++ ) res.a[i][i] = 1 ;
    while( b ){
        if( b & 1 ) res = Mul( res , a ) ;
        b >>= 1 ;
        a = Mul( a , a ) ;
    }
    return res ;
}

int main(){
    while( ~scanf("%d",&m) ){
        scanf("%s",s);
        n = strlen(s);
        for( int i = 0 ; i < n ; i++ ){
            val[i] = s[i] - '0';
        }
        Matrix Mat;
        memset( Mat.a , 0 , sizeof(Mat.a) );
        Mat.a[n-1][0] = 1 ;
        Mat.a[0][0] = 1 ;
        for( int i = 1 ; i < n ; i++ ){
            Mat.a[i][i] = 1 ;
            Mat.a[i-1][i] = 1 ;
        }
        Matrix ans = quick( Mat , m ) ;
        for( int i = 0 ; i < n ; i++ ){
            int tmp = 0 ;
            for( int j = 0 ; j < n ; j ++ ){
                tmp = ( tmp + val[j] * ans.a[j][i] ) % 2 ;
            }
            printf("%d",tmp);
        }printf("\n");
    }
    return 0 ;
}

HDU2842
公式:F(n) = 2*F( n - 2 ) + F(n-1) + 1
思路:i前面都为0,且i为1时,i+1才能变成0,
当使位置为n的字符为0时,需要满足n-2前面都变成0,步数就是F(n-2) , 且n-1为1,
然后变n-1,因为要从后往前变,所以先要+F(n-2)(变n时将前n-2项改变,此时要变回去) ,再加上F(n-1)
利用F(n-2)的步数,再加一步,将n-2变成1,才能改变n-1,就是F(n-1)
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int MOD = 200907;
int n ;
struct Matrix{
    LL a[4][4];
};

Matrix Mul( Matrix x , Matrix y ){
    Matrix ans ;
    memset( ans.a , 0 , sizeof(ans) );
    for( int i = 0 ; i < 3 ; i++ ){
        for( int j = 0 ; j < 3 ; j++ ){
            for( int k = 0 ; k < 3 ; k++ ){
                ans.a[i][j] = ( ans.a[i][j] + x.a[i][k] * y.a[k][j] % MOD ) % MOD ;
            }
        }
    }
    return ans ;
}

Matrix quick( Matrix x , int b ){
    Matrix ans;
    memset( ans.a , 0 , sizeof(ans) );
    for( int i = 0 ; i < 3 ; i++ ) ans.a[i][i] = 1 ;
        while( b ){
            if( b & 1 ) ans = Mul( ans , x );
            x = Mul(x,x);
            b >>= 1 ;
        }
        return ans ;
    }

    int main(){
        while( scanf("%d",&n) && n ){
            if( n == 1 ) printf("1\n");
            else if( n == 2 ) printf("2\n");
            else{
                Matrix ans ;
                memset( ans.a , 0 , sizeof(ans.a) );
                ans.a[0][0] = 1 ; ans.a[0][1] = 2 ; ans.a[0][2] = 1 ; 
                ans.a[1][0] = 1 ; ans.a[1][1] = 0 ; ans.a[1][2] = 0 ; 
                ans.a[2][0] = 0 ; ans.a[2][1] = 0 ; ans.a[2][2] = 1 ; 
                Matrix tmp ;
                memset( tmp.a , 0 ,sizeof(tmp.a) );
                tmp.a[0][0] = 2 ; tmp.a[1][0] = 1 ; tmp.a[2][0] = 1 ;
                Matrix t = quick( ans , n - 2 );
                int res = 0 ;
                for( int i = 0 ; i < 3 ; i++ ){
                    res = ( res + t.a[0][i] * tmp.a[i][0] ) % MOD ;
                }
                printf("%d\n",res);
            }
        }
        return 0 ;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值