3012: Fibnacci Numbers
总提交: 199 测试通过:55
描述
The fibnacci numbers are as follows:
f[1] = 1; f[2] = 2;
f[n] = f[n - 1] + f[n - 2];
And s[n] is defined:
Now ,give you the integer number a, x and n, you should calculate the ans, and the ans is defined as follows:
ans = as[x] % n;
You must pay attention to the range of the number: 1 ≤ a ≤ 100000000; 1 ≤ x ≤ 1000000000; 2 ≤ n ≤ 100000000.
输入
The input contains several test cases. For each test case, only line contains three integer numbers a, x and n separated by spaces.
The end of the input is indicated by a line containing three zeros separated by spaces.
输出
For each test case the output is only one integer number ans in a line.
样例输入
样例输出
题目来源
解题思路:首先要知道
1.先用斐波那契前n项平方和公式简化一下表达式; ans = a^(F(x)*F(x+1) - 1) % n
2.指数比较大,用降幂公式 a ^ b % c = a^(b%phi(c) + phi(c) ) % c
3.斐波那契的项数比较多(x比较大),F(x)%phi(n)考虑矩阵快速幂取模解决
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 1000000000
#define mod 1000000007
#define maxn 100006
#define lowbit(x) (x&-x)
#define eps 1e-10
ll a,n,x,ph;
struct node
{
ll x[2][2];
}b,c;
ll ol(ll x)
{
ll i,res=x;
for(i=2;i*i<=x;i++)
{
if(x%i)
continue;
res=res-res/i;
while(x%i==0)
x/=i;
}
if(x>1)
res=res-res/x;
return res;
}
node q2(node a,node b,ll MOD)
{
node p;
int i,j,k;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
p.x[i][j]=0;
for(k=0;k<2;k++)
p.x[i][j]+=a.x[i][k]*b.x[k][j];
p.x[i][j]%=MOD;
}
return p;
}
node q1(node x,ll y,ll MOD)
{
node pp=c;
while(y)
{
if(y&1)
pp=q2(pp,x,MOD);
x=q2(x,x,MOD);
y>>=1;
}
return pp;
}
ll q3(ll x,ll y,ll MOD)
{
ll res=1;
while(y)
{
if(y&1)
res=(res*x)%MOD;
x=(x*x)%MOD;
y>>=1;
}
return res;
}
void init()
{
b.x[0][0]=b.x[0][1]=1;
b.x[1][0]=1;b.x[1][1]=0;
c.x[0][0]=c.x[1][1]=1;
c.x[0][1]=c.x[1][0]=0;
}
int main(void)
{
node ans;
init();
while(scanf("%lld%lld%lld",&a,&x,&n),a+x+n)
{
ph=ol(n);
ans=q1(b,x+1,ph);
ll ans1=(ans.x[0][0]*ans.x[0][1]%ph+ph-1)%ph+ph;
ll ans2=q3(a,ans1,n);
printf("%lld\n",ans2);
}
return 0;
}
/*
400000 21 13
400000 400014 16384
*/