函数

本文介绍了一个数学挑战问题,即根据给定的n、q和p,计算Fn%p的值,其中Fn由q和n定义。文章给出了计算公式及算法实现思路,包括等比数列求和的方法。

Description

东东 上幼儿园学习了数学,刚刚学会1+1=2,就让教信息学竞赛的爸爸给他出题,并且扬言越难越好,好吧,为了让东东知道自己对数学理解的肤浅,东东爸 给出下面的题目:

Fn=qn+1q+1 (n为奇数)

Fn=qn1q+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=qn1qn2+qn3qn4++q2q1+q0
Fn=(s0+s1+s2++sn/21)(sq)
当n为偶数时
Fn=qn1qn2+qn3qn4++q1q0
Fn=(s0+s1+s2++sn/21)(q1)
之后就是简单的等比数列求和啦,可以用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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值