zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    linux高可用集群(HA)原理详解
    【C#/WPF】修改图像的DPI、Resolution
    【C#】图像的变形/变换/扭曲。用Emgu或YLScsFreeTransform(FreeImageTransformation)或MagickImage
    【C#】遍历List列表的同时,移除访问到的元素
    【WPF】动态设置Binding的ConverterParameter转换器参数
    【SVN/Visual Studio】清除/更换AnkhSVN的用户登录信息
    【C#】允许泛型方法<T>返回空值Null
    【C#】时间日期格式转换:long和DateTime相互转换
    【C#/WPF】ListView的MVVM例子,及禁止拖动ListView的头部Header
    【C#/WPF】保存BitmapImage数据到文件中
  • 原文地址:https://www.cnblogs.com/ymzjj/p/9948370.html
Copyright © 2011-2022 走看看