您的位置:首页 > 产品设计 > UI/UE

HDU 5667 Sequence

2016-04-25 11:16 288 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5667

题意:给一个递推式,求第n项。





思路:

Fn全部是以a为底数的幂,所以我们先忽略底数,将第n项的指数算出来,再计算fn。

设指数为pi,p1 = 0,p2 = b,pn = b + c * p(n-1) + p(n-2)

由于n非常大,所以我们需要用矩阵+快速幂来计算。

根据转移式我们可以构造出一个矩阵乘法,乘一个矩阵就转移一项。

还有一个问题是如果指数很大,也需要取模,假设现在需要算a^y % p的结果,我们需要对y进行取模来保存结果,如果存在a^x
% p = 1,我们就可以将y对x取模,也就是a^y
= a^x *a^x*....a^(y % x) = 1*1*...*a^(y % x)。因为P为质数,所以此时的x为p-1(费马小定理)。


{ pi-2 , pi-1 , b }

×

{ 0 1 0 } => { pi-1 , pi , b }

{ 1 c 0 }

{ 0 1 1 }

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007

int T;
int a,b,c;
int p;
LL n;

struct martix
{
LL a[3][3];

};

martix multi( martix x, martix y ,int p)
{
martix temp;

rep(i,0,2)
rep(j,0,2)
{
temp.a[i][j] = 0;
rep(k,0,2)
{
temp.a[i][j]+=x.a[i][k]*y.a[k][j];
temp.a[i][j]%=p;
}
}
return temp;
}

int pow_mod(int a , int b , int m ) //快速幂取模
{
a%=m;
LL ans = 1;
LL temp = a;
while(b)
{
if ( b & 1 ) ans = ( ans * temp ) % m;
temp = ( temp * temp ) % m;
b>>=1;
}
return (int)ans;
}

int main()
{
cin>>T;
while(T--)
{
scanf("%I64d %d %d %d %d",&n,&a,&b,&c,&p);

if ( n <=2 )
{
if ( n == 1 ) puts("1");
else printf("%d\n",pow_mod(a,b,p));
continue;
}
if ( a % p == 0 )
{
puts("0");
continue;
}
//需要转移n-2次
n-=2;
// 矩阵快速幂  x存答案,一开始为单位矩阵
martix x; //temp记矩阵的2^i幂
martix temp;
rep(i,0,2)
rep(j,0,2) x.a[i][j] = (i==j)?1:0;
temp.a[0][0] = temp.a[0][2] = temp.a[1][2] = temp.a[2][0] = 0;
temp.a[0][1] = temp.a[1][0] = temp.a[2][1] = temp.a[2][2] = 1;
temp.a[1][1] = c%(p-1);
while( n )
{
if ( n & 1 ) x = multi( temp , x  , (p-1));
temp = multi( temp,temp,(p-1) );
n>>=1;
}
LL t[3] = {0,b,b};//初始矩阵{ p1  p2  b }
LL ans[3];//记录最终的矩阵{ pn-1  pn  b }
rep(i,0,2)
{
ans[i] = 0;
rep(j,0,2)
ans[i] = ( ans[i] + t[j]*x.a[j][i] ) % (p-1);
}
printf("%d\n",pow_mod( a , ans[1], p ));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: