UVA10870递推关系(矩阵乘法)
生活随笔
收集整理的這篇文章主要介紹了
UVA10870递推关系(矩阵乘法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給以個遞推f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d.,給你n,d,a1,a2..ad ,f[1],f[2]..f[d],讓你求f[n]%m.
思路:
? ? ? 比較基礎的矩陣題目,每次都構造一個d*d的矩陣,然后用快速冪求出來它的n-1次冪,然后在求出乘積就行了,簡單構造,沒有什么坑點。
? ? ? ? ??
#include<stdio.h>
#include<string.h>
typedef struct
{
? ?long long Mat[16][16];
}MAT;
long long n ,MOD ,d;
MAT mm(MAT a ,MAT b)
{
? ?MAT c;
? ?memset(c.Mat ,0 ,sizeof(c.Mat));
? ?for(int i = 1 ;i <= d ;i ++)
? ?for(int j = 1 ;j <= d ;j ++)
? ?for(int k = 1 ;k <= d ;k ++)
? ?c.Mat[i][j] = (c.Mat[i][j] + a.Mat[i][k] * b.Mat[k][j])%MOD;
? ?return c;
}
MAT Quick(MAT a ,long long b)
{
? ?MAT c;
? ?memset(c.Mat ,0 ,sizeof(c.Mat));
? ?for(int i = 1 ;i <= d ;i ++)
? ?c.Mat[i][i] = 1;
? ?while(b)
? ?{
? ? ? if(b&1) c = mm(c ,a);
? ? ? a = mm(a ,a);
? ? ? b>>=1;
? ?}
? ?return c;
}
int main ()
{
? ?long long D[16] ,F[16] ,i;
? ?MAT A;
? ?while(~scanf("%lld %lld %lld" ,&d ,&n ,&MOD) && d + n + MOD)
? ?{
? ? ? for(i = 1 ;i <= d ;i ++)?
? ? ? {
? ? ? ? ?scanf("%lld" ,&D[i]);
? ? ? ? ?D[i] %= MOD;
? ? ? }
? ? ? for(i = 1 ;i <= d ;i ++)?
? ? ? {
? ? ? ? ?scanf("%lld" ,&F[i]);
? ? ? ? ?F[i] %= MOD;
? ? ? }
? ? ? if(n <= d)
? ? ? {
? ? ? ? ?printf("%lld\n" ,F[n]);
? ? ? ? ?continue;
? ? ? }
? ? ? memset(A.Mat ,0 ,sizeof(A.Mat));
? ? ? int x = 2 ,y = 1;
? ? ? for(i = 2 ;i <= d ;i ++)
? ? ? {
? ? ? ? ?A.Mat[x][y] = 1;
? ? ? ? ?x ++ ,y ++;
? ? ? }
? ? ? for(i = 1 ;i <= d ;i ++)
? ? ? A.Mat[i][d] = D[d-i+1];
? ? ??
? ? ??
? ? ? A = Quick(A ,n - 1);
? ? ? long long Ans = 0;
? ? ? for(i = 1 ;i <= d ;i ++)
? ? ? {
? ? ? ? ?Ans += F[i] * A.Mat[i][1];
? ? ? ? ?Ans %= MOD;
? ? ? }
? ? ? printf("%lld\n" ,Ans);
? ?}
? ?return 0;
}
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ?
? ?
? ?
? ?
? ? ? 給以個遞推f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d.,給你n,d,a1,a2..ad ,f[1],f[2]..f[d],讓你求f[n]%m.
思路:
? ? ? 比較基礎的矩陣題目,每次都構造一個d*d的矩陣,然后用快速冪求出來它的n-1次冪,然后在求出乘積就行了,簡單構造,沒有什么坑點。
? ? ? ? ??
#include<stdio.h>
#include<string.h>
typedef struct
{
? ?long long Mat[16][16];
}MAT;
long long n ,MOD ,d;
MAT mm(MAT a ,MAT b)
{
? ?MAT c;
? ?memset(c.Mat ,0 ,sizeof(c.Mat));
? ?for(int i = 1 ;i <= d ;i ++)
? ?for(int j = 1 ;j <= d ;j ++)
? ?for(int k = 1 ;k <= d ;k ++)
? ?c.Mat[i][j] = (c.Mat[i][j] + a.Mat[i][k] * b.Mat[k][j])%MOD;
? ?return c;
}
MAT Quick(MAT a ,long long b)
{
? ?MAT c;
? ?memset(c.Mat ,0 ,sizeof(c.Mat));
? ?for(int i = 1 ;i <= d ;i ++)
? ?c.Mat[i][i] = 1;
? ?while(b)
? ?{
? ? ? if(b&1) c = mm(c ,a);
? ? ? a = mm(a ,a);
? ? ? b>>=1;
? ?}
? ?return c;
}
int main ()
{
? ?long long D[16] ,F[16] ,i;
? ?MAT A;
? ?while(~scanf("%lld %lld %lld" ,&d ,&n ,&MOD) && d + n + MOD)
? ?{
? ? ? for(i = 1 ;i <= d ;i ++)?
? ? ? {
? ? ? ? ?scanf("%lld" ,&D[i]);
? ? ? ? ?D[i] %= MOD;
? ? ? }
? ? ? for(i = 1 ;i <= d ;i ++)?
? ? ? {
? ? ? ? ?scanf("%lld" ,&F[i]);
? ? ? ? ?F[i] %= MOD;
? ? ? }
? ? ? if(n <= d)
? ? ? {
? ? ? ? ?printf("%lld\n" ,F[n]);
? ? ? ? ?continue;
? ? ? }
? ? ? memset(A.Mat ,0 ,sizeof(A.Mat));
? ? ? int x = 2 ,y = 1;
? ? ? for(i = 2 ;i <= d ;i ++)
? ? ? {
? ? ? ? ?A.Mat[x][y] = 1;
? ? ? ? ?x ++ ,y ++;
? ? ? }
? ? ? for(i = 1 ;i <= d ;i ++)
? ? ? A.Mat[i][d] = D[d-i+1];
? ? ??
? ? ??
? ? ? A = Quick(A ,n - 1);
? ? ? long long Ans = 0;
? ? ? for(i = 1 ;i <= d ;i ++)
? ? ? {
? ? ? ? ?Ans += F[i] * A.Mat[i][1];
? ? ? ? ?Ans %= MOD;
? ? ? }
? ? ? printf("%lld\n" ,Ans);
? ?}
? ?return 0;
}
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ? ??
? ?
? ?
? ?
? ?
總結
以上是生活随笔為你收集整理的UVA10870递推关系(矩阵乘法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVA10341解方程(二分)
- 下一篇: UVA11021麻球繁衍