您的位置:首页 > 其它

hdu 4565 So Easy! (共轭构造+矩阵快速幂)

2015-05-03 11:45 381 查看
题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=4565

题目大意:

  给出a,b,n,m,求出

的值,

解题思路:

  因为题目中出现了开根号,和向上取整后求余,所以用矩阵快速幂加速求解过程的时候,会产生误差,就很自然地想到了凑数,因为(a-1)^2<b<a^2,得出0<a-sqrt(b)<1,则无论n取多大,(a-sqrt(b))^n都是小于1的,(a-sqrt(b))^n 与 (a+sqrt(b))^n共轭,两者展开后会相互抵销,所以((a-sqrt(b))^n + (a+sqrt(b))^n)为整数,假设((a-sqrt(b))^n + (a+sqrt(b))^n)用sn表示,则sn*(a+sqrt(b))+(a-sqrt(b)) = Sn+1 - (a^2-b)*Sn-1,进一步得出 Sn+1 = 2*a*Sn - (a*a - b) * Sn-1,

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define LL __int64
LL a, b, n, m;
struct mat
{
LL p[2][2];
};

mat mul (mat x, mat y);
mat pow (mat x, mat y, LL z);

int main ()
{
mat x, y;
while (scanf ("%I64d %I64d %I64d %I64d", &a, &b, &n, &m) != EOF)
{
memset (x.p, 0, sizeof(x.p));
memset (y.p, 0, sizeof(y.p));
x.p[0][0] = (2*(a*a+b)%m+m)%m;//要用long long,int相乘的时候会溢出
x.p[0][1] = (2*a) % m;
y.p[0][0] = (2*a) % m;
y.p[0][1] = 1;
y.p[1][0] = ((b-a*a)%m+m)%m;
//y.p[1][0] = ((b-a*a)+m)%m;//这样取余是错误的,因为还有可能是负数,害wa了好几次
x = pow (x, y, n-1);
printf ("%I64d\n", x.p[0][1]);
}
return 0;
}

mat mul (mat x, mat y)
{
int i, j, k;
mat z;
memset (z.p, 0, sizeof(z.p));
for (i=0; i<2; i++)
for (j=0; j<2; j++)
{
for (k=0; k<2; k++)
z.p[i][j] += x.p[i][k] * y.p[k][j];
z.p[i][j] = (z.p[i][j] + m )% m;
}
return z;
}
mat pow (mat x, mat y, LL z)
{
while (z)
{
if (z % 2)
x = mul(x,y);
y = mul (y, y);
z /= 2;
}
return x;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: