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 }
原文地址:https://www.cnblogs.com/qqky/p/6922664.html