HDU - 5667 Sequence(矩阵快速幂+费马小定理)

写这题的时候压根不知道费马小定理是啥

HDU - 5667 

Problem Description
     Holion August will eat every thing he has found.

     Now there are many foods,but he does not want to eat all of them at once,so he find a sequence.

fn=1,ab,abfcn1fn2,n=1n=2otherwise

     He gives you 5 numbers n,a,b,c,p,and he will eat  fn  foods.But there are only p foods,so you should tell him  fn  mod p.
 

Input
     The first line has a number,T,means testcase.

     Each testcase has 5 numbers,including n,a,b,c,p in a line.

    1T10,1n1018,1a,b,c109 , p  is a prime number,and  p109+7 .
 

Output
     Output one number for each case,which is  fn  mod p.
 

Sample Input
  
  
1 5 3 3 3 233
 

Sample Output
  
  
190

题意:很简单不说了

思路:推出a的系数,用矩阵快速幂求a的系数(系数还不是我推的,队友推的),但是这个时候发现不能直接用系数去modp,所以需要get新知识,早上写题真是WA到傻才明白我可能漏了些知识。这里的系数需要mod(p-1),因为首先p是一个质数,所以如果a不是p的倍数的话,肯定与p满足互质这个条件,所以满足费马小定理的式子,所以每一个a^(p-1)%(p)肯定是1的,所以a的系数里每p-1个对modp的贡献都是1,所以对系数需要mod(p-1)。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
#define ll long long

ll Mod,c;
struct node
{
    ll mat[3][3];
    node()
    {
        for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            mat[i][j] = 0;
    }
};
node operator*(node a,node b)
{
    node temp;
    for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
    for(int k = 0; k < 3; k++)
        temp.mat[i][j] = (temp.mat[i][j] + (a.mat[i][k] * b.mat[k][j])%(Mod-1))%(Mod-1);
    return temp;
}
ll qpow(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1) ans = (ans*a)%Mod;
        a = (a*a)%Mod;
        b = b >> 1;
    }
    return ans;
}
ll mpow(ll n)
{
    if(n == 1) return 0;
    if(n == 2) return 1;
    n = n-2;
    node e,ans;
    ll temp[3] = {1,0,1};
    e.mat[0][0] = c, e.mat[0][1] = 1, e.mat[0][2] = 1;
    e.mat[1][0] = 1, e.mat[2][2] = 1;
    for(int i = 0; i < 3; i++) ans.mat[i][i] = 1;
    while(n)
    {
        if(n&1) ans = ans*e;
        e = e*e;
        n = n >> 1;
    }
    ll ret = 0;
    for(int i = 0; i < 3; i++)
        ret = (ret + (ans.mat[0][i]*(temp[i]%(Mod-1)))%(Mod-1))%(Mod-1);
    return ret;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll a,b,n;
        cin >> n >> a >> b >> c >> Mod;
        if(a%Mod == 0)
        {
            cout << 0 << endl;
            continue;
        }
        ll temp = b*mpow(n)%(Mod-1);
        ll ans = qpow(a,temp);
        cout << ans << endl;
    }
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值