1. 程式人生 > >快速冪演算法及矩陣快速冪

快速冪演算法及矩陣快速冪

Description
給定三個數A, B, K, 求 A的B次方除以K的餘數 。
Input
輸入只有一行,為三個正整數A(1 <= A <= 2000000000), B(1 <= B <= 2000000000), K(1 <= K <= 10000)。
Output
一個整數,(A ^ B) % K 的值。
Sample Input
11 100 7
Sample Output

4

#include<iostream>
using namespace std;
int main()
{
	long long a,b;
	int k,i,j,s=1;
	cin>>a;
	cin>>b;
	cin>>k;
	a=a%k;
	while(b)
	{
		if(b%2==1)
			s=(s*a)%k;
		b=b/2;
		a=(a*a)%k; 
	}
	cout<<s<<endl;
	return 0;
}
以下為a^b快速冪演算法模板
	int s=1,a,b;
        cin>>a>>b;
	while(b)
	{
		if(b%2==1)
		<span style="white-space:pre">	</span>s=s*a;
		b=b/2;
		a=a*a; 
	}
	cout<<s<<endl;

使用矩陣快速冪演算法求斐波那契數列

Description

In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn
 − 2 for n ≥ 2. F

Input

a single line containing n (where 0 ≤ n ≤ 100,000,000,000)

Output

print Fn mod 1000000007 in a single line.

Sample Input

99999999999

Sample Output

669753982

Hint

An alternative formula for the Fibonacci sequence is


As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by


Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:

AC程式碼//矩陣快速冪模模板

#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
long long a[3][3]={{0,0,0},{0,1,1},{0,1,0}};
long long t[3][3]={{0,0,0},{0,0,0},{0,0,0}};//相當於temp,替換作用
long long s[3][3]={{0,0,0},{0,1,0},{0,0,1}};//初始為單位矩陣
int main()
{
	int k,i,j;
	long long n,b;
	cin>>n;
	b=n;
	while(b)
	{
		if(b%2==1)
		{
		    memset(t,0,sizeof(t));
			for(i=1;i<=2;i++)
				for(j=1;j<=2;j++)
				 	for(k=1;k<=2;k++)
				 		t[i][j]=(t[i][j]+(s[i][k]*a[k][j])%1000000007)%1000000007;//t=s*a
			for(i=1;i<=2;i++)
				for(j=1;j<=2;j++)
				s[i][j]=t[i][j];//s=t;
		}
		b=b/2;
		memset(t,0,sizeof(t));
		for(i=1;i<=2;i++)
			for(j=1;j<=2;j++)
				for(k=1;k<=2;k++)
					t[i][j]=(t[i][j]+(a[i][k]*a[k][j])%1000000007)%1000000007;//t=a*a;
		for(i=1;i<=2;i++)
			for(j=1;j<=2;j++)
			a[i][j]=t[i][j];//a=t;		
	}
	cout<<s[1][2]<<endl;
	return 0;
}


Problem Description 
Now, have a break, I, Jason, am tired of making the problem. 
Let us solve a math problem. 
F[1] = 1; 
F[2] = 1; 
F[n] = (A * F[n - 1] + B * F[n - 2]) mod 1000000007 
Given A, B, and n, you are to calculate the value of F[n]. 
 
Input 
The input consists of multiple test cases. Each test case contains three 
integers A, B and n on a single line (1<=A,B<=1000,1<=n<=100000000). 
  Three zeros signal the end of input and this test case is not to be 
processed. 
 
Output 
For each test case, print the value of F[n] on a single line. 
 
Sample Input 

1 1 3 
1 2 10 
0 0 0 
 
Sample Output 

341 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<algorithm>
#include<sstream>
#define LL long long
using namespace std;
const int MAX=1000000007;
LL a[2][2];
LL t[2][2];
int main()
{
    LL x;
    while(cin>>x)
    {
        LL y,n;
        cin>>y>>n;
        if(x==0&&y==0&&n==0)
            return 0;
        LL b=n-2;
        LL s[2][2]={{1,0},{0,1}};
        a[0][0]=x;
        a[0][1]=y;
        a[1][0]=1;
        a[1][1]=0;
        while(b)
        {
            if(b%2==1)
            {
            memset(t,0,sizeof(t));
            for(int i=0;i<=1;i++)
                for(int j=0;j<=1;j++)
                    for(int k=0;k<=1;k++)
                        t[i][j]=(t[i][j]+s[i][k]*a[k][j])%MAX;
            for(int i=0;i<=1;i++)
                for(int j=0;j<=1;j++)
                    s[i][j]=t[i][j];
            }
        b=b/2;
        memset(t,0,sizeof(t));
        for(int i=0;i<=1;i++)
            for(int j=0;j<=1;j++)
                for(int k=0;k<=1;k++)
                    t[i][j]=(t[i][j]+a[i][k]*a[k][j])%MAX;
        for(int i=0;i<=1;i++)
            for(int j=0;j<=1;j++)
                a[i][j]=t[i][j];
        }
        cout<<(s[0][0]+s[0][1])%MAX<<endl;
    }
    return 0;
}