hdu 1757

 

A Simple Math Problem

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


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

 

若一矩阵的列数与另一矩阵的行数相等,则可定义这两个矩阵的乘积。如 A 是 m×n 矩阵和 B 是 n×p矩阵,它们是乘积 AB 是一个 m×p 矩阵,其中
(AB)[i, j] = A[i, 1] * B[1, j] + A[i, 2] * B[2, j] + ... + A[i, n] * B[n, j] 对所有 i 及 j。
此乘法有如下性质:
(AB)C = A(BC) 对所有 k×m 矩阵 A, m×n 矩阵 B 及 n×p 矩阵 C ("结合律").
(A + B)C = AC + BC 对所有 m×n 矩阵 A 及 B 和 n×k 矩阵 C ("分配律")。
C(A + B) = CA + CB 对所有 m×n 矩阵 A 及 B 和 k×m 矩阵 C ("分配律")。
要注意的是:可置换性不一定成立,即有矩阵 A 及 B 使得 AB ≠ BA。

     下面我们研究一下这道题如何运用矩阵。
     假设我们已有一个1*10的矩阵f0 f1 f2...f9 只要将其乘以一下矩阵,就可以推导至矩阵f1 f2 f3 ...f10:
                    0 0 0 0 0 0 0 0 0 a(9)
                           1 0 0 0 0 0 0 0 0 a(8)
                           0 1 0 0 0 0 0 0 0 a(7)
                           0 0 1 0 0 0 0 0 0 a(6)
                           0 0 0 1 0 0 0 0 0 a(5)
                           0 0 0 0 1 0 0 0 0 a(4)
                           0 0 0 0 0 1 0 0 0 a(3)
                           0 0 0 0 0 0 1 0 0 a(2)
                           0 0 0 0 0 0 0 1 0 a(1)
                           0 0 0 0 0 0 0 0 1 a(0)  
     设这个矩阵为D。
     f1,f2,f3...f10再乘以这个矩阵就可以推导至f2,f3,f4...f11。以此类推,递推的过程就变成了不断乘以这个矩阵的过程。这样,如果我们要得到fk,我们就得将初始矩阵(f0,f1,f2...f10)乘以D^(k-9),从而得出目标矩阵(目标矩阵的最后一项即为所求)。而D^(k-9)我们可以用10^3*log(k-9)的时间计算出来,此题圆满解决。

#include<iostream>
using namespace std;
int ans,k,m,TEMP[10][10],NOW[10][10],Tui[10][10];
int work(int n)
{
     if (n>1)
     {
       work(n/2);
       memset(TEMP,0,sizeof(TEMP));
       for (int i=0;i<=9;++i)
       for (int j=0;j<=9;++j)
       for (int k=0;k<=9;++k)
       TEMP[i][j]=(TEMP[i][j]+(NOW[i][k]*NOW[k][j])%m)%m;
       for (int i=0;i<=9;++i)
       for (int j=0;j<=9;++j)
       NOW[i][j]=TEMP[i][j];
       if (n%2==1)
       {
           memset(TEMP,0,sizeof(TEMP));
           for (int i=0;i<=9;++i)
           for (int j=0;j<=9;++j)
           for (int k=0;k<=9;++k)
           TEMP[i][j]=(TEMP[i][j]+(NOW[i][k]*Tui[k][j])%m)%m;
       }
       for (int i=0;i<=9;++i)
       for (int j=0;j<=9;++j)
       NOW[i][j]=TEMP[i][j];
   }
}
int main()
{
     while (cin>>k>>m)
     {
           memset(Tui,0,sizeof(Tui));
           memset(NOW,0,sizeof(NOW));
           for (int i=0;i<=8;++i)
           {
               Tui[i+1][i]=1;
               NOW[i+1][i]=1;
           }
           for (int i=0;i<=9;++i)
           {
               cin>>Tui[9-i][9];
               NOW[9-i][9]=Tui[9-i][9];
           }
           if (k<10) cout<<k%m<<endl; else
           {
               work(k-9);
               ans=0;
               for (int i=0;i<=9;++i)
               ans=(ans+(NOW[i][9]*i)%m)%m;
               cout<<ans<<endl;
           }
     }
     return(0);
}


   /*                          A Simple Math Problem
Time limit: 1000MS Memory limit: 32768K
Total Submit: 5 Accepted: 4

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*109 , m < 104 )
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

解题的关键在于如何构建矩阵

code:

 


#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define le 11

typedef struct{

    int map[le][le];

}re;

re init,unit,ar;

int k,m;

 

void initdata(){

    int i,j;

    for(i = 0;i < 10;i++)

        for(j = 0;j < 10;j++){

            if(i - 1 == j)  init.map[i][j] = 1;

            else            init.map[i][j] = 0;

            if(i == j)   unit.map[i][j] = 1;

            else         unit.map[i][j] = 0;

            ar.map[i][j] = 0;

        }

    for(i = 9;i >= 0;i--)

        ar.map[9-i][0] = i;

}

 

void input(){

    int i;

    for(i = 0;i < 10;i++)

        scanf("%d",&init.map[0][i]);

}

 

re mul(re va,re vb){

    int i,j,k;

    re c;

    for(i = 0;i < 10;i++)

        for(j = 0;j < 10;j++){

            c.map[i][j] = 0;

            for(k = 0;k < 10;k++)

                c.map[i][j] += va.map[i][k] * vb.map[k][j];

            c.map[i][j] %= m;

        }

    return c;

}

 

int cal(){

    int i = k - 9;

    re p = unit,q = init,c;

    while(i > 1){

        if(i % 2){

            p = mul(p,q);

            i--;

        }

        else {

            q = mul(q,q);

            i >>= 1;

        }

    }

    c = mul(p,q);

    c = mul(c,ar);

    return c.map[0][0];

}

 

void deal(){

    int ans;

    if(k <= 9){

        printf("%d\n",k % m);

        return ;

    }

    ans = cal();

    printf("%d\n",ans);

}

 

int main(void){

    initdata();

    while(scanf("%d%d",&k,&m)==2){

        input();

        deal();

    }

    return 0;

}

*/

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值