HDU3221Brute-force Algorithm(矩陣快速冪&&指數降冪)
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3221
Problem Description
Professor Brute is not good at algorithm design. Once he was asked to solve a path finding problem. He worked on it for several days and finally came up with the following algorithm:
Any fool but Brute knows that the function “funny” will be called too many times. Brute wants to investigate the number of times the function will be called, but he is too lazy to do it.
Now your task is to calculate how many times the function “funny” will be called, for the given a, b and n. Because the answer may be too large, you should output the answer module by P.
Any fool but Brute knows that the function “funny” will be called too many times. Brute wants to investigate the number of times the function will be called, but he is too lazy to do it.
Now your task is to calculate how many times the function “funny” will be called, for the given a, b and n. Because the answer may be too large, you should output the answer module by P.
Input
There are multiple test cases. The first line of the input contains an integer T, meaning the number of the test cases.
For each test cases, there are four integers a, b, P and n in a single line.
You can assume that 1≤n≤1000000000, 1≤P≤1000000, 0≤a, b<1000000.
For each test cases, there are four integers a, b, P and n in a single line.
You can assume that 1≤n≤1000000000, 1≤P≤1000000, 0≤a, b<1000000.
Output
For each test case, output the answer with case number in a single line.
Sample Input
3
3 4 10 3
4 5 13 5
3 2 19 100
Sample Output
Case #1: 2
Case #2: 11
Case #3: 12
從第三項開始 a的指數為斐波那契數列
由於比較大 我們根據公式a^b%p=a^(b%phi(p)+phi(p))%p b>=phi(p)對指數進行降冪
然後再快速冪取模即可得到結果
對p=1的情況進行特判;
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 2;
struct matrax
{
LL m[N][N];
};
matrax E={
1,0,
0,1
};
matrax A={
1,1,
1,0
};
LL a,b,p,n,mm;
matrax multi(matrax a,matrax b)
{
matrax c;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
c.m[i][j]=0;
for(int k=0;k<N;k++)
c.m[i][j]+=a.m[i][k]*b.m[k][j];
if(c.m[i][j]>mm)
c.m[i][j]=c.m[i][j]%mm+mm;
}
}
return c;
}
matrax pow(matrax a,LL n)
{
matrax ans=E,p=a;
while(n){
if(n&1){
ans=multi(ans,p);
n--;
}
n>>=1;
p=multi(p,p);
}
return ans;
}
LL phi(LL n)
{
LL rea=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
rea=rea-rea/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
LL quick_mod(LL a,LL b)
{
LL ans=1;
while(b){
if(b&1){
ans=ans*a%p;
b--;
}
b>>=1;
a=a*a%p;
}
return ans;
}
int main()
{
int t=1,cas;
cin>>cas;
while(cas--){
cin>>a>>b>>p>>n;
mm=phi(p);
printf("Case #%d: ",t++);
if(n==1){
printf("%I64d\n",a%p);
continue;
}
if(n==2){
printf("%I64d\n",b%p);
continue;
}
if(n==3){
printf("%I64d\n",a*b%p);
continue;
}
if(p==1){
puts("0");
continue;
}
matrax g=pow(A,n-2);
LL m1,m2,num1,num2;
m1=g.m[1][0];
m2=g.m[0][1]+g.m[1][1];
if(m2>mm) m2=m2%mm+mm;
num1=quick_mod(a,m1);
num2=quick_mod(b,m2);
printf("%I64d\n",num1*num2%p);
}
return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 2;
struct matrax
{
LL m[N][N];
};
matrax E={
1,0,
0,1
};
matrax A={
1,1,
1,0
};
LL a,b,p,n,mm;
matrax multi(matrax a,matrax b)
{
matrax c;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
c.m[i][j]=0;
for(int k=0;k<N;k++)
c.m[i][j]+=a.m[i][k]*b.m[k][j];
if(c.m[i][j]>mm)
c.m[i][j]=c.m[i][j]%mm+mm;
}
}
return c;
}
matrax pow(matrax a,LL n)
{
matrax ans=E,p=a;
while(n){
if(n&1){
ans=multi(ans,p);
n--;
}
n>>=1;
p=multi(p,p);
}
return ans;
}
LL phi(LL n)
{
LL rea=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
rea=rea-rea/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
LL quick_mod(LL a,LL b)
{
LL ans=1;
while(b){
if(b&1){
ans=ans*a%p;
b--;
}
b>>=1;
a=a*a%p;
}
return ans;
}
int main()
{
int t=1,cas;
cin>>cas;
while(cas--){
cin>>a>>b>>p>>n;
mm=phi(p);
printf("Case #%d: ",t++);
if(n==1){
printf("%I64d\n",a%p);
continue;
}
if(n==2){
printf("%I64d\n",b%p);
continue;
}
if(n==3){
printf("%I64d\n",a*b%p);
continue;
}
if(p==1){
puts("0");
continue;
}
matrax g=pow(A,n-2);
LL m1,m2,num1,num2;
m1=g.m[1][0];
m2=g.m[0][1]+g.m[1][1];
if(m2>mm) m2=m2%mm+mm;
num1=quick_mod(a,m1);
num2=quick_mod(b,m2);
printf("%I64d\n",num1*num2%p);
}
return 0;
}
相關文章
- 矩陣快速冪矩陣
- 矩陣快速冪總結矩陣
- 矩陣快速冪(快忘了)矩陣
- 矩陣快速冪加速最短路矩陣
- 矩陣快速冪最佳化矩陣
- 【矩陣乘法】【快速冪】遞推矩陣
- BZOJ 3329 Xorequ:數位dp + 矩陣快速冪矩陣
- HDU 1005 Number Sequence(矩陣快速冪)矩陣
- 演算法學習:矩陣快速冪/矩陣加速演算法矩陣
- 費馬小定理 + 費馬大定理 + 勾股數的求解 + 快速冪 + 矩陣快速冪 【模板】矩陣
- HDU 2256Problem of Precision(矩陣快速冪)矩陣
- HDU 2157 How many ways?? (矩陣快速冪)矩陣
- POJ 3613 Cow Relays 矩陣乘法Floyd+矩陣快速冪矩陣
- HDU 2276 - Kiki & Little Kiki 2 (矩陣快速冪)矩陣
- 從斐波那契到矩陣快速冪矩陣
- BZOJ3329: Xorequ(二進位制數位dp 矩陣快速冪)矩陣
- 第?課——基於矩陣快速冪的遞推解法矩陣
- POJ 3233 Matrix Power Series (矩陣快速冪+等比數列二分求和)矩陣
- bzoj4887: [Tjoi2017]可樂(矩陣乘法+快速冪)矩陣
- HDU 4549 M斐波那契數列(矩陣快速冪+費馬小定理)矩陣
- 尤拉降冪
- poj--2778DNA Sequence+AC自動機+矩陣快速冪矩陣
- 快速冪
- 快速乘/快速冪
- 快速冪模板
- 越獄(快速冪)
- 整數冪
- 快速冪的運用
- 快速冪的寫法
- 數論模運算以及快速冪小解
- 菜鳥初嘗快速冪
- Raising Modulo (快速冪取模)AI
- 漲薪【貪心】【快速冪】
- Quick Pow: 如何快速求冪UI
- 快速冪的初步認識(Java)Java
- 矩陣指數的定義矩陣
- BZOJ4589: Hard Nim(FWT 快速冪)
- HDU 2197 本原串 (規律+快速冪)
- 力扣之 4 的冪 & 3 的冪 & 2 的冪(遞迴思想)力扣遞迴