zoukankan      html  css  js  c++  java
  • Fy's dota2 题解

    题目描述

    Fy 觉得自己玩 cf,lol 这种高端游戏已经够厉害了,于 是他决定去玩 dota2.结果 fy 的鼠标右键坏了,所以他就等 到 2250 买了把闪烁匕首,用跳刀前进,准备去送泉水。但 是 fy 一次最多前进 k 的距离,泉水离 fy 现在的距离是 n。 Fy 想知道他到泉水的方案数。

    输入输出格式

    输入格式:

    第一行 2 个整数:k,n

    输出格式:

    一行 1 个整数:代表答案对 7777777 取膜的结果

    数据范围约定

    对于 30%的数据:n<=1000,k<=10

    对于 100%的数据:1<=n<=2^31-1,1<=k<=10

    题解

     更具题目我们先来推一下,我们发现当允许的跳跃距离为 k 时,调到 i 新增加的方案数只会从(i-k)~ (i - 1)提供贡献,而其他的方案都可以归类到其中,所以我们就可以得到下面这个递推公式

        

      初始量是f[1] = 1, f[0] = 1;

      而由于数据范围是到2^31所以我们要考虑用矩阵乘法来优化递推:

        

    代码

     #include <bits/stdc++.h>
     using namespace std;
     #define LL long long
     
     struct Martix
     {
         LL a[12][12];
         Martix friend operator * (Martix x, Martix y)
             {
                 Martix ans;
                 memset(ans.a, 0, sizeof(ans));
                 for(int i = 1; i <= 11; ++ i)
                     for(int j = 1; j <= 11; ++ j)
                         for(int k = 1; k <= 11; ++ k)
                             ans.a[i][j] = (ans.a[i][j] + (x.a[i][k] * y.a[k][j]) % 7777777) % 7777777; 
                 return ans;
             }
     
         Martix friend operator % (Martix x, int m)
             {
                 for(int i = 1; i<= 11; ++ i)
                     for(int j = 1; j <= 11; ++ j)
                         x.a[i][j] = x.a[i][j] % m;
                 return x;
             }
     };
     int m, n;
     LL f[15], sum[15];
     Martix ksm(Martix x, LL b, LL mod)
         {
             Martix ret;
             memset(ret.a, 0, sizeof(ret.a));
             for(int i = 1; i <= m; ++ i)    ret.a[1][i] = f[i];
             for(;b; b >>= 1, x = (x * x) % mod)
                 if(b & 1)    ret = (ret * x) % mod;
             return ret;
         }
     
     int main()
     {
     //    freopen("fyfy.in","r",stdin);
     //    freopen("fyfy.out","w",stdout);
         LL ans = 0;
         Martix zy;
         memset(zy.a, 0, sizeof(zy.a));
         scanf("%d%d", &m, &n);
         if(n > m)
         {
             for(int i = 1; i <= m; ++ i) zy.a[i][m] = 1, f[i] = 1;
             for(int i = 2; i <= m; ++ i)    zy.a[i][i - 1] = 1;
             for(int i = 1; i <= m; ++ i)
                 for(int j = 1; j < i; ++ j)
                     f[i] = f[i] + f[j];
             zy = ksm(zy, n - 1, 7777777);
     //        for(int i = 1; i <=m; ++ i)
     //            ans = (ans + ((long long)f[i] * zy.a[i][1]) % 7777777) % 7777777;
             printf("%lld
    ", zy.a[1][1]);
         }
         else
         {
             for(int i = 1; i <= n; ++ i)    f[i] = sum[i - 1] + 1, sum[i] = sum[i - 1] + f[i];
             printf("%lld
    ", f[n]);
         }
         return 0;
     }

    考场上写Wa掉了,可我怎么也没想到是把转移矩阵和初始向量相乘的时候算错了,为了避免这个问题我们可以把初始向量放在快速幂的0次矩阵的第一行,这样就不会错了。

        

  • 相关阅读:
    LeetCode算法题-Trim a Binary Search Tree(Java实现)
    LeetCode算法题-Non-decreasing Array(Java实现)
    LeetCode算法题-Image Smoother(Java实现)
    Node.js 官方文档中文版
    jade 网上看到一个不错的demo 分享 一下 链接
    jade 的 考古
    标题党 数据抓取与管理
    最近面试 有人问 sqlite 用过么 sqlite 不是 嵌入式的 开发 么 难道最近还 web开发 了?
    嗯 想写个demo 苦于没数据
    客户端 jQuery 跨端口 调用 node 服务端
  • 原文地址:https://www.cnblogs.com/2020pengxiyue/p/9342250.html
Copyright © 2011-2022 走看看