杭电2010和2011级同学如何加入ACM集训队? |
A Simple Math ProblemTime 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
Sample Output
|
若一矩阵的列数与另一矩阵的行数相等,则可定义这两个矩阵的乘积。如 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;
}
*/