• 5、魔力手环--网易2017春招


    [编程题] 魔力手环
    时间限制:1秒
    空间限制:32768K
    小易拥有一个拥有魔力的手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。 
    输入描述:
    输入数据包括两行: 第一行为两个整数n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000),以空格分隔 第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.
     
     
    输出描述:
    输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。
     
    输入例子:
    3 2 1 2 3
     
    输出例子:
    8 9 7
     
    解题思路:本题使用暴力的方式,每次进行处理,处理k次,会超时
     1 #include <iostream>
     2  
     3 using namespace std;
     4  
     5 int main()
     6 {
     7     int n;
     8     int k;
     9     while(cin>>n>>k)
    10     {
    11         int a[n];
    12         for(int i=0;i<n;i++)
    13         {
    14             cin>>a[i];
    15         }
    16         for(int i=0;i<k;i++)
    17         {
    18             int tmp = a[0];
    19             int j=0;
    20             for(;j<n-1;j++)
    21             {
    22                 a[j] = (a[j] + a[j+1])%100;
    23             }
    24             a[j] = (a[j]+tmp)%100;
    25         }
    26         int i=0;
    27         for(;i<n-1;i++)
    28         {
    29             cout<<a[i]<<" ";
    30         }
    31         cout<<a[i];
    32  
    33     }
    34     return 0;
    35 }
    以上代码只通过60%

    正确做法:思路:n个数的环进行移动相加,考虑到矩阵行、列变换可以完成这种移动和相加,于是构造出快速幂矩阵,快速幂矩阵M和原矩阵S相乘得到一次移动的结果,那么F(n+1) = M^n*S(这里的幂和乘法是矩阵的运算),很容易得到如下递推示例:
    [[1 1 0] [0 1 1] [1 0 1]]*[[a][b][c]] = [[a+b][b+c][c+a]], 如此,已经确定了快速幂矩阵M,那么就要考虑如何相乘得到最快的幂求解速度。
     1 #include <iostream>
     2 #include<cstring>
     3 using namespace std;
     4  
     5 int main()
     6 {
     7     int n,k;
     8     cin >> n >> k;
     9     int d[n];//存放结果
    10     for(int i=0;i<n;++i) 
    11     {
    12         cin >> d[i];
    13     }
    14     //构造快速幂矩阵
    15     int Mul[n][n];
    16     for(int i=0;i<n-1;++i) 
    17     {
    18         fill(Mul[i],Mul[i]+n,0);
    19         Mul[i][i] = 1;
    20         Mul[i][i+1] = 1;
    21     }
    22     fill(Mul[n-1],Mul[n-1]+n,0);
    23     Mul[n-1][0] = 1;
    24     Mul[n-1][n-1] = 1;
    25     //转化为2进制,进行二分搜索
    26     while(k)  
    27     {
    28         if(k&1) 
    29         {
    30             int temp[n];
    31             fill(temp, temp+n, 0);
    32             for(int i=0;i<n;++i) 
    33             {
    34                 for(int j=0;j<n;++j) 
    35                 {
    36                     temp[i] += (Mul[i][j]*d[j]);
    37                     temp[i] = temp[i]%100;
    38                 }
    39             }
    40             memcpy(d, temp, sizeof(d));
    41         }
    42         k = k>>1;
    43         int temp[n][n];
    44         for(int i=0;i<n;++i)  
    45         {
    46             fill(temp[i],temp[i]+n,0);
    47         }
    48         for(int i=0;i<n;++i) 
    49         {
    50             for(int j=0;j<n;++j) 
    51             {
    52                 for(int k=0;k<n;++k) 
    53                 {
    54                     temp[i][j]+=Mul[i][k]*Mul[k][j];//二维矩阵相乘
    55                 }
    56                 temp[i][j] %= 100;//快速幂取余中,a^k % c =  (a % c)^k % c
    57             }
    58         }
    59         for(int i=0;i<n;++i)
    60         {
    61             memcpy(Mul[i],temp[i],sizeof(Mul[i]));
    62         }
    63     }
    64     //输出结果
    65     for(int i=0;i<n-1;++i) 
    66     {
    67         cout << d[i] <<" ";
    68     }
    69     cout << d[n-1] << endl;
    70     return 0;
    71 }
  • 相关阅读:
    【零基础】极星9.5套利详解
    【零基础】极星9.3资金字段详解
    【零基础】易盛9.0API入门三:下单并查询订单状态
    【零基础】极星量化扩展一:如何做跨合约的交易
    【零基础】极星9.3止盈止损用法详解
    【零基础】极星9.3几种套利的说明
    【零基础】MT4量化入门三:写一个双均线指标
    概率与似然
    PCA的计算方法
    隐藏节点数的选择
  • 原文地址:https://www.cnblogs.com/qqky/p/6922664.html
Copyright © 2020-2023  润新知