zoukankan      html  css  js  c++  java
  • 18.03.26 vijos1067Warcraft III 守望者的烦恼

    背景

    守望者-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,否则可能会溢出

    来源

    杜杜我爱你个人原创

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <stdlib.h>
     5 #include <math.h>
     6 
     7 using namespace std;
     8 const int maxn=20,mod=7777777;
     9 long long int f[maxn];//存放到第几个监狱时的走法
    10 
    11 struct mat{
    12     long long int a[maxn][maxn];
    13 }res,ans;
    14 
    15 //matrix multiply j1*j2 n dimension(square)
    16 mat cheng1(mat j1,mat j2,int n){
    17     mat tmp;
    18     for(int i=1;i<=n;i++)
    19         for(int j=1;j<=n;j++)
    20             tmp.a[i][j]=0;
    21     for(int i=1;i<=n;i++)
    22         for(int j=1;j<=n;j++)
    23             for(int k=1;k<=n;k++)
    24                 tmp.a[i][j]=(j1.a[i][k]*j2.a[k][j])%mod+tmp.a[i][j];
    25     return tmp;
    26 }
    27 
    28 
    29 //quickpow k dimension n multi_n
    30 mat qp(int k,int n){
    31     for(int i=1;i<=k;i++)
    32         for(int j=1;j<=k;j++){
    33             if(i==j)ans.a[i][j]=1;
    34             else ans.a[i][j]=0;
    35         }
    36     while(n){
    37         if(n&1)
    38             ans=cheng1(res,ans,k);
    39         res=cheng1(res,res,k);
    40         n>>=1;
    41     }
    42     return ans;
    43 }
    44 
    45 int main()
    46 {
    47     int k,n;//k级 n个
    48     scanf("%d%d",&k,&n);
    49     f[0]=1;
    50     for(int i=1;i<=k;i++){
    51         f[i]=0;
    52         for(int j=i-1;j>=0&&j>=i-k;j--){
    53             f[i]+=f[j];
    54         }
    55     }
    56     for(int i=1;i<=k-1;i++){
    57         res.a[i][i+1]=1;
    58         res.a[k][i]=1;
    59     }
    60     res.a[k][k]=1;
    61     res=qp(k,n-k);
    62     long long int m[maxn]={0};
    63     for(int j=1;j<=k;j++){
    64         m[k]+=res.a[k][j]*f[j];
    65     }
    66     printf("%lld
    ",m[k]%mod);
    67     return 0;
    68 }
    View Code

    大概是矩阵快速幂优化dp的经典题型,学习了

    状态转移方程非常好想,所以一开始天真的我想用滚动数组把它全部循环一遍

    然而数据太大了……当然是没法过的

    所以要用矩阵乘法来缩短时间,算法了解一下->点这里

    然后就是那个mod777...7……这句话我看了很久才明白是啥意思……

    不过改完还是wa了几次,40分,原因是我只是在结果那边简单地%了一下mod(这有个毛用啊)

    其实中间计算的时候数据就已经溢出了

    所以又改了一下矩阵乘法计算过程中的数,因为反正都相当于是减了很多个mod所以对最后结果没有什么影响

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    interview ms1 N_Dorm
    interview ms1 robert move **
    LeetCode OJ-- Jump Game II **
    LeetCode OJ-- Jump Game
    LeetCode OJ-- Palindrome Partitioning II ***
    LeetCode OJ--Palindrome Partitioning **
    LeetCode OJ--Palindrome Number
    LeetCode OJ-- Linked List Cycle II **
    3dContactPointAnnotationTool开发日志(十一)
    3dContactPointAnnotationTool开发日志(十)
  • 原文地址:https://www.cnblogs.com/yalphait/p/8650130.html
Copyright © 2011-2022 走看看