HDU1757 - A Simple Math Problem - 矩阵快速幂

1.题目描述

A Simple Math Problem

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4507    Accepted Submission(s): 2716


Problem Description
Lele now is thinking about a simple function f(x).

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
 

Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
 

Output
For each case, output f(k) % m in one line.
 

Sample Input

10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
 

Sample Output

45 104
 

Author
linle
 

Source
2007省赛集训队练习赛(6)_linle专场
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   1575  1588  3117  2276  2256 
2.题意概述:

函数满足——If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);

要你求f(k) % mod;

3.解题思路:

我开始想的就是递推,果断地T了,然后。。。大半天最后看discuss才发现是矩阵快速幂。然后总结完二分再来总结快速幂,突然发现二者其实是存在联系的,就是把连乘每次折半地运算,尤其对于矩阵幂运算,大大加速了计算。

言归正传,网上盗了一张递推图

HDU1757 - A Simple Math Problem - 矩阵快速幂_第1张图片

这样就把问题转化为求矩阵的n-9次幂

4.AC代码:

#include 
#define INF 0x3f3f3f3f
#define maxn 20010
#define N 10
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int a[N], f[N], k, mod;
struct Matrix
{
  ll mat[N][N];
  Matrix operator*(const Matrix &m) const
  {
    Matrix tmp;
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
      {
        tmp.mat[i][j] = 0;
        for (int k = 0; k < N; k++)
        {
          tmp.mat[i][j] += mat[i][k] * m.mat[k][j] % mod;
          tmp.mat[i][j] %= mod;
        }
      }
    return tmp;
  }
};
ll Pow(Matrix &m, int k)
{
  Matrix ans;
  memset(ans.mat, 0, sizeof(ans.mat));
  for (int i = 0; i < N; i++)
    ans.mat[i][i] = 1;
  k -= 9;
  while (k)
  {
    if (k & 1)
      ans = ans * m;
    k >>= 1;
    m = m * m;
  }
  ll sum = 0;
  for (int i = 0; i < N; i++)
    sum += ans.mat[0][i] * f[N - i - 1] % mod;
  sum %= mod;
  return sum;
}
void init(Matrix &m)
{
  memset(m.mat, 0, sizeof(m.mat));
  for (int i = 0; i < N; i++)
    m.mat[0][i] = a[i];
  for (int i = 0; i < N - 1; i++)
    m.mat[i + 1][i] = 1;
  for (int i = 0; i < N; i++)
    f[i] = i;
}
int main()
{
#ifndef ONLINE_JUDGE
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
  long _begin_time = clock();
#endif
  Matrix m;
  while (~scanf("%d%d", &k, &mod))
  {
    for (int i = 0; i < N; i++)
      scanf("%d", &a[i]);
    init(m);
    if (k < 10)
      printf("%d\n", k % mod);
    else
      printf("%lld\n", Pow(m, k));
  }
#ifndef ONLINE_JUDGE
  long _end_time = clock();
  printf("time = %ld ms.", _end_time - _begin_time);
#endif
  return 0;
}

你可能感兴趣的:(快速幂)