今天复习了一下快速幂, 又把长久以来未解决的那道矩阵的乘方解决了。好开心啊!
那么先来复习一下快速幂;
ep:1
这次题目很简单。给你一个整数N,求NN的个位数。
#include<stdio.h>
#include<math.h>
#define X 10
int main()
{
int T,i,j,t,ans;
__int64 n;
int powermod(int a,int b);
while(scanf("%d",&T)!=EOF)
{
for(i=1;i<=T;i++)
{
scanf("%I64d",&n);
ans=powermod(n,n);
printf("%d\n",ans);
}
}
return 0;
}
int powermod(int a,int b){
__int64 ans=1,pow=a;
while(b!=0)
{
if(b&1) ans=(ans*pow)%X;
pow=(pow*pow)%X;
b=b/2;
}
return (int)ans;
}
ep2 :
给你两个数列:{Ai},{Bi},长度都为H,求(A1B1+A2B2+ ... +AHBH)mod M的值。
当然,作为学霸,杰哥不是不会做,而是太懒了。于是他又像聪明的程序员——你来求助了。请帮他快速算出该表达式的值。
#include<stdio.h>
int main()
{
int T,i,j,m,h,a,b;
__int64 sum;
int powermod(int a,int b,int c);
while(scanf("%d",&T)!=EOF)
{
for(i=1;i<=T;i++)
{
sum=0;
scanf("%d",&m);
scanf("%d",&h);
for(j=1;j<=h;j++)
{
scanf("%d %d",&a,&b);
sum+=powermod(a,b,m);
}
sum=sum%m;
printf("%I64d\n",sum);
}
}
}
int powermod(int a,int b,int c)
{
__int64 ans=1,pow=a;
while(b!=0){
if(b%2!=0) ans=(ans*pow)%c;
pow=(pow*pow)%c;
b/=2;
}
return(int)ans;
}
所谓快速幂,就是不断地缩小问题,化为子问题。
当为奇数时,那么就先乘以原来的那个,因为当n是奇数时,肯定是只进行第一次的if条件里面的那个语句,后面的话应该都是偶数了。
若是偶数时,就pow进行自乘。
最终肯定会有个1,所以,ans乘进去后就是最终结果了。
那么,对于矩阵乘方来说也是可以化成这样的问题,只不过,最好把每次矩阵的相乘和快速幂的函数分开来写,这样会显得更清晰点。
ep 3:
yyf最近在学习线性代数。他发现可以用矩阵乘法来求解递推式。例如求解斐波那契数列。
先构造一个矩阵A
1 1
1 0
再用斐波那契数列的前两项f2 ,f1 构造一个矩阵B
1
1
A*B
可得
2
1
即
f3
f2
易知
(A^n)*B
可以得到一个
f(n+2)
f(n+1)
构成的矩阵
那么问题来了。
斐波那契数列第n项的值为多少
Input
输入第一个数字为样例组数T(T<=10000)
每组样例为一个数字n(n<=100000000)
Output
输出斐波那契数列的第n项值(输出的数字可能会比较大,输出结果对10007取余)
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define mod 10007
int n;
int sum[10][10],s[10][10];
void calutate(int a[10][10],int b[10][10]){
int i,j,k;
int c[10][10]={0};
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++){
c[i][j]+=a[i][k]*b[k][j];
}
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
a[i][j]=c[i][j]%mod;
}
int Martix(int k){
memset(sum,0,sizeof(sum));
int i,j;
//构造单位矩阵;
for(i=1;i<=2;i++) sum[i][i]=1;
while(k!=0){
if(k%2) calutate(sum,s);
calutate(s,s);
k=k/2;
}
int ans=0;
ans=(sum[2][1]*1+sum[2][2]*1)%mod;
return ans;
}
int main(){
int T;
cin>>T;
while(T--){
s[1][1]=1; s[1][2]=1; s[2][1]=1; s[2][2]=0;
cin>>n;
n=n-1;
int ans=Martix(n);
cout<<ans<<endl;
}
}
一开始也是这样写的,但是不能输出,后来把int 中的sum的值改小了后就可以了,这里的原因不是十分清楚。