Description
东东 上幼儿园学习了数学,刚刚学会1+1=2,就让教信息学竞赛的爸爸给他出题,并且扬言越难越好,好吧,为了让东东知道自己对数学理解的肤浅,东东爸 给出下面的题目:
Fn=qn+1q+1 (n为奇数)
Fn=qn−1q+1 (n为偶数)
给定n和q,求
Fn
的值。
东东不畏艰难困苦,终于没有算出来,同时也懂得了数学的博大精深。你能算出来么?
Input
第一行三个整数x、y、z来描述q,q=
xy
+z;
第二行一个正整数n;
第三行一个正整数p。
Output
输出 Fn % p 的值。
Hint
对于60%的数据, 0<=x,y<=50000,1<=z<=50000, 0<=n<=105, 1<=p<108
对于100%的数据,0<=x,y<=50000,1<=z<=50000,0<=n<=109,1<=p<108
Sample Input
3 0 5
3
70546
Sample Output
31
Key To Problem
设s=
q2
当n为奇数时
Fn=qn−1−qn−2+qn−3−qn−4+……+q2−q1+q0
则
Fn=(s0+s1+s2+……+sn/2−1)∗(s−q)
当n为偶数时
Fn=qn−1−qn−2+qn−3−qn−4+……+q1−q0
则
Fn=(s0+s1+s2+……+sn/2−1)∗(q−1)
之后就是简单的等比数列求和啦,可以用exgcd来搞,然而我用的是二分,不过这些都是细节就不要在意啦
CODE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a1,a2,a3;
int n,MOD;
ll pow(ll x,int y)
{
ll ans=1;
while(y)
{
if(y&1)
ans=(x*ans)%MOD;
x=(x*x)%MOD;
y>>=1;
}
return ans;
}
ll ef(ll x,int sum)
{
if(sum<0)
return 0;
if(sum==0)
return 1;
ll ans=0;
if(sum%2==0)
ans=((pow(x,sum/2+1)+1)*ef(x,sum/2-1)%MOD+pow(x,sum/2))%MOD;
else
ans=(pow(x,sum/2+1)+1)*ef(x,sum/2)%MOD;
return ans%MOD;
}
int main()
{
// freopen("function.in","r",stdin);
// freopen("function.out","w",stdout);
cin>>a1>>a2>>a3>>n>>MOD;
ll q=(pow(a1,(int)a2)+a3)%MOD;
ll s=(q*q)%MOD;
if(n%2==1)
{
ll a=ef(s,n/2-1)*(s-q+MOD)%MOD+1;
cout<<a%MOD<<endl;
}else
{
ll a=ef(s,n/2-1)*(q-1);
cout<<a%MOD<<endl;
}
return 0;
}