• VOJ1067 【矩阵经典7 构造矩阵】


    任意门:https://vijos.org/records/5be95b65d3d8a1366270262b

    背景

    守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看完所有的监狱,只是从入口进入,然后再从出口出来就算完成任务了。

    描述

    头脑并不发达的warden最近在思考一个问题,她的闪烁技能是可以升级的,k级的闪烁技能最多可以向前移动k个监狱,一共有n个监狱要视察,她从入口进去,一路上有n个监狱,而且不会往回走,当然她并不用每个监狱都视察,但是她最后一定要到第n个监狱里去,因为监狱的出口在那里,但是她并不一定要到第1个监狱。

    守望者warden现在想知道,她在拥有k级闪烁技能时视察n个监狱一共有多少种方案?

    格式

    输入格式

    第一行是闪烁技能的等级k(1<=k<=10)
    第二行是监狱的个数n(1<=n<=2^31-1)

    输出格式

    由于方案个数会很多,所以输出它 mod 7777777后的结果就行了

    样例1

    样例输入1

    2
    4
    

    样例输出1

    5
    

    限制

    各个测试点1s

    提示

    把监狱编号1 2 3 4,闪烁技能为2级,
    一共有5种方案
    →1→2→3→4
    →2→3→4
    →2→4
    →1→3→4
    →1→2→4

    小提示:建议用int64,否则可能会溢出

    题意概括:

    给出可闪现的距离 K 房间个数 N,问到达终点的方案数;

    解题思路:

    很明显的DP,DP的转移方程也显而易见 F(N) = F(N-1)+F(N-2)+ ... + F(N-K);

    找出递推式,很显然可以用矩阵来优化,并且系数为 1,So easy!

    以为到这就解决问题了,太粗心啦,注意数据范围,注意数据精度!!!要用 long long

    Ac code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define LL long long
    using namespace std;
    const int MAXN = 11;
    const LL Mod  = 7777777;
    int N, K;
    
    struct mat
    {
        LL m[MAXN][MAXN];
    }base, tmp, ans;
    
    mat muti(mat a, mat b)
    {
        mat res;
        memset(res.m, 0, sizeof(res.m));
    
        for(int i = 1; i <= K; i++)
        for(int j = 1; j <= K; j++){
            if(a.m[i][j]){
                for(int k = 1; k <= K; k++){
                    res.m[i][k] = (res.m[i][k] + a.m[i][j]*b.m[j][k])%Mod;
    //                res.m[i][k] = res.m[i][k]%Mod;
                }
            }
        }
        return res;
    }
    
    mat qpow(mat a, int n)
    {
        mat res;
        memset(res.m, 0, sizeof(res));
        for(int i = 1; i <= K; i++) res.m[i][i] = 1LL;
        while(n){
            if(n&1) res = muti(res, a);
            n>>=1;
            a = muti(a, a);
        }
        return res;
    }
    
    int main()
    {
        scanf("%d%d", &K, &N);
        memset(base.m, 0, sizeof(base.m));
        base.m[0][1] = 1LL;
        for(int i = 1; i <= K; i++){
            for(int j = 0; j < i; j++)
                base.m[i][1] += base.m[j][1]%Mod;
        }
    
        if(N <= K) printf("%lld
    ", base.m[N][1]);
        else{
            memset(tmp.m, 0, sizeof(tmp.m));
            for(int i = 1; i < K; i++){
                tmp.m[i][i+1] = 1LL;
            }
            for(int i = 1; i <= K; i++) tmp.m[K][i] = 1LL;
    
            tmp = qpow(tmp, N-K);
            mat ans = muti(tmp, base);
    
            printf("%lld
    ", ans.m[K][1]%Mod);
        }
        return 0;
    }
  • 相关阅读:
    Qt源文件和ui文件的关系
    使用moveToThread线程并正确回收内存的方式
    mysql设置某字段不可重复
    使用curl创建简单的性能监控工具
    你是不是那个带不动的队友
    这样的面试你能通过吗
    浅谈测试观
    自动化测试如何准备测试数据
    关于双十二崩盘的一些思考
    浅谈测试环境
  • 原文地址:https://www.cnblogs.com/ymzjj/p/9948370.html
Copyright © 2020-2023  润新知