zoukankan      html  css  js  c++  java
  • 操作数~矩阵快速幂解法

    链接:https://www.nowcoder.com/acm/contest/109/C
    来源:牛客网

    题目描述

    给定长度为n的数组a,定义一次操作为:
    1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007;
    2. 执行a = s;
    现在问k次操作以后a长什么样。

    输入描述:

    第一行两个整数n,k(1 <= n <= 2000, 0 <= k <= 1,000,000,000);
    第二行n个整数表示a数组(0 <= a
    i
    <= 1,000,000,000)。

    输出描述:

    一行n个整数表示答案。
    示例1

    输入

    3 1
    1 2 3

    输出

    1 3 6
    示例2

    输入

    5 0
    3 14 15 92 6

    输出

    3 14 15 92 6


    这题非常容易找到矩阵A,
    1 1 1 1 1
    0 1 1 1 1
    0 0 1 1 1
    0 0 0 1 1
    0 0 0 0 1
    就是这样的矩阵,
    但是要注意一点 n有2000;
    所以直接写出这个矩阵不行,压缩一下就OK了

       mat operator * (mat & a) {
            mat ans;
            for (int i = 0 ; i < maxn ; i++) {
                    for (int j = 0 ; j <= i ; j++ ) {
                             ans.m[i] = (ans.m[i] + m[j] * a.m[i - j]) % mod;
                   }
            }
            return ans;
       }

      由于规律性非常明显,所以可以用一个一维数组存储

      

    然后就是常规的矩阵快速幂操作。
    不过这题他们说有其他的解法
    找规律好像可以做,但是我不会。
    只能想到矩阵快速幂的方法
    矩阵快速幂有点慢,不过能AC也OK


     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <vector>
     4 #include <queue>
     5 #include <cstring>
     6 #include <string>
     7 #include <map>
     8 using namespace std;
     9 const int maxn = 2000;
    10 const long  long  mod = 1e9 + 7;
    11 typedef long long LL;
    12 struct mat {
    13     LL m[maxn];
    14     mat() {
    15         memset(m, 0, sizeof(m));
    16     }
    17     mat operator * (mat & a) {
    18         mat ans;
    19         for (int i = 0 ; i < maxn ; i++) {
    20             for (int j = 0 ; j <= i ; j++ ) {
    21                 ans.m[i] = (ans.m[i] + m[j] * a.m[i - j]) % mod;
    22             }
    23         }
    24         return ans;
    25     }
    26 };
    27 mat modexp(mat a, LL b) {
    28     mat ans;
    29     for (int i = 0 ; i < maxn ; i++) ans.m[i] = 1;
    30     while(b) {
    31         if (b & 1 ) ans = ans * a;
    32         b = b >> 1;
    33         a = a * a;
    34     }
    35     return ans;
    36 }
    37 int main() {
    38     LL n, k;
    39     mat a, b;
    40     scanf("%lld%lld", &n, &k );
    41     for (int i = 0 ; i < n ; i++) {
    42         scanf("%lld", &b.m[i]);
    43         a.m[i] = 1;
    44     }
    45     if (k == 0) {
    46         for (int i = 0 ; i < n ; i++) {
    47             printf("%lld", b.m[i]);
    48             if (i != n - 1) printf(" ");
    49             else printf("
    ");
    50         }
    51         printf("
    ");
    52     } else {
    53         a = modexp(a, k - 1);
    54         b = b * a;
    55         for (int i = 0 ; i < n ; i++) {
    56             printf("%lld", b.m[i]);
    57             if (i != n - 1) printf(" ");
    58             else printf("
    ");
    59         }
    60     }
    61     return 0;
    62 }


  • 相关阅读:
    数字IC笔试题 ——Cadence前端设计2018
    Verilog -- 序列检测器及其最小状态数
    Verilog -- 状态机
    数字IC笔试 -- 汇顶设计验证2018
    Systemverilog -- 数据类型
    深度学习资料
    Lucene介绍与使用
    java全角、半角字符的关系以及转换
    怎样用正则表达式去除文本中的标点符号
    linux下转换windows文件格式,启动脚本报错问题解决
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/8995192.html
Copyright © 2011-2022 走看看