URAL 1518 Jedi Riddle 3 矩阵快速幂

本文介绍了一种使用矩阵快速幂解决特定数学问题的方法,通过构建矩阵结构体并定义相关操作来实现高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1518. Jedi Riddle 3

Time limit: 1.5 second
Memory limit: 64 MB

Background

The death is a funny thing. It is discussed only by the ones, who never died, while those, who are already dead, prefer keeping silence. That is why few people know, what exactly happens with a human after his death. A body is undoubtedly remains under ground forever... But the way of a soul was discovered only by Anton Hamster, who was a disciple of legendary Vasily Slipman (you may look through the problems  "Jedi riddle" and  "Jedi riddle 2" for more information about Mr. Slipman).
Mr. Hamster carried out a sequence of experiments and found out, that, however it sounds pity, a soul neither soars into the sky nor falls under ground. It just finds oneself at one of the countless levels of the Twilight, where it is condemned to stay till the end of time. In theory, a soul may be returned into the Real World and resurrected in a new body. The only question is how to do it...

Problem

Surely, Anton knew, that it was possible to get to any level of the Twilight straight from the Real World. You should only know a Key - and the Gates of the Twilight will open before you. Inter vivos, Mr. Slipman himself visited  N first levels using  N Keys  Ki he found by brute force. But Vasily failed to find the Key to the ( N+1)-th and the following levels. He just made a remark, that one had to use  N Shift Numbers  Ci and the Modular Number  Y.
But Mr. Hamster could excel his Teacher and succeeded in finding a universal formula for the Key  Kito the Gates of any level of the Twilight. Here is the formula:  Ki = ( Ki-1* CN +  Ki-2*CN-1 +  Ki-3*CN-2 + ... +  Ki-N*C1) modulo  Y.
And now Anton wants to organize the second coming of Mr. Slipman into our sinful world. The only thing he needs is to calculate the Key to the Gates of the Twilight's  X-th level, where the Teacher's soul is concealed in expectation of freedom.

Input

The first line contains the integer numbers  N (1 ≤  N ≤ 100),  X ( N <  X < 2 28) and  Y (2 ≤  Y < 2 28). The second line contains  N integer Keys  Ki (0 ≤  Ki ≤ 100). The third line contains  Ninteger Shift Numbers  Ci (0 ≤  Ci ≤ 1).

Output

You should output the desired Key  KX.

Sample

input output
3 6 73
12 91 65
1 1 0
22





就是 那个加粗的公式  写成矩阵相乘就ok了。 轻松a。 
矩阵快速幂100*100 大小的矩阵差不多极限了。

#include<stdio.h>
#include<string.h>
#define Matr 105 //矩阵大小,注意能小就小   矩阵从1开始   所以Matr 要+1 
#define ll __int64
struct mat//矩阵结构体,a表示内容,size大小 矩阵从1开始   但size不用加一
{
    ll a[Matr][Matr];
    mat()//构造函数
    {
        memset(a,0,sizeof(a));
    }
};
int Size;
ll mod ;

mat multi(mat m1,mat m2)//两个相等矩阵的乘法,对于稀疏矩阵,有0处不用运算的优化 
{
    mat ans=mat(); 
    for(int i=1;i<=Size;i++)
        for(int j=1;j<=Size;j++)
            if(m1.a[i][j])//稀疏矩阵优化 
                for(int k=1;k<=Size;k++)
                    ans.a[i][k]=(ans.a[i][k]+m1.a[i][j]*m2.a[j][k])%mod; //i行k列第j项
    return ans;
}

mat quickmulti(mat m,ll n)//二分快速幂 
{
    mat ans=mat();
    int i;
    for(i=1;i<=Size;i++)ans.a[i][i]=1;
    while(n)
    {
        if(n&1)ans=multi(m,ans);//奇乘偶子乘 挺好记的.
        m=multi(m,m);
        n>>=1;
    }
    return ans;
}

void print(mat m)//输出矩阵信息,debug用   
{  
    int i,j;  
    printf("%d\n",Size);  
    for(i=1;i<=Size;i++)  
    {  
        for(j=1;j<=Size;j++)
			printf("%d ",m.a[i][j]);  
        printf("\n");  
    }  
}  
int main()
{
	int n; 
	while(scanf("%d%d%d",&Size,&n,&mod)!=EOF) 
	{
		mat gouzao=mat(),chu=mat();
		for(int i=1;i<Size;i++)
			gouzao.a[i+1][i]=1;
		for(int i=1;i<=Size;i++)
			scanf("%I64d",&chu.a[1][i]);
		for(int i=1;i<=Size;i++)
			scanf("%I64d",&gouzao.a[i][Size]); 

		 

		printf("%I64d\n",multi(chu,quickmulti(gouzao,n-1)).a[1][1]); 
	}
	return 0;
}

/*
ans^=n -
mat ans=mat();
ans.size=Size;
初始化ans矩阵
ans=quickmulti(ans,n,mod);

void print(mat m)//输出矩阵信息,debug用 
{
    int i,j;
    printf(%dn,m.size);
    for(i=1;i=m.size;i++)
    {
        for(j=1;j=m.size;j++)printf(%d ,m.a[i][j]);
        printf(n);
    }
}
*/







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值