http://poj.org/problem?id=1320
题意很简单,有序列 1,2,3...(a-1),a,(a+1)...b 要使以a为分界的 前缀和 和 后缀和 相等 求a,b
因为序列很特殊所以我们用数学方法就可以解决 :
求和: a*(a-1)/2 = (a+1+b)(b-a)/2
化简: 2a2 = b2 + b
两边乘4,构造完全平方项 (2b+1)2 - 8a2 = 1
令 x = 2*b+1;
y = a;
我们就得到了一个形如Pell方程x2 - Dy2 = 1 的式子 x2 - 8y2 = 1
这题就是求Pell方程的第K个解 , 因为方程已经告诉你了
所以我们可以目测出最小解以用来构造矩阵来求出后面的解
下面就是构造系数矩阵的方法:
已知Pell方程为 x2 - Dy2 = 1
为了得到第k个解,我们需要构造系数矩阵
为了得到系数矩阵,我们必须知道该方程的最小特解 x0,y0
于是我们就能得到系数矩阵:
xk yk 就是Pell方程的第k个解
对于Pell方程最小特解的求法,可以参照我上一篇 http://www.cnblogs.com/Felix-F/p/3222741.html
当然这题一眼就能看出最小特解为x=3,y=1
用矩阵快速幂小加了一下速 (应该是逗比了..这样反而复杂度高了....直接记录各层次的矩阵就行...
struct matrix
{
LL ma[2][2];
};
int n = 2;
matrix operator * (matrix a,matrix b)
{
matrix temp;
memset(temp.ma,0,sizeof(temp.ma));
for(int i = 0; i < n ; i++)
for(int j = 0; j < n ; j++)
for(int k = 0 ; k < n ; k++)
temp.ma[i][j] = temp.ma[i][j] + (a.ma[k][i] * b.ma[j][n-k-1]);
return temp;
}
matrix operator + (matrix a,matrix b)
{
for(int i = 0; i < n ; i++)
for(int j = 0; j < n ; j++)
a.ma[i][j] = (a.ma[i][j] + b.ma[i][j]) ;
return a;
}
matrix m_pow(matrix a,int n)
{
if(n == 1) return a;
matrix temp = m_pow(a,n/2);
if(n & 1) return temp * temp * a;
else return temp * temp ;
}
int main()
{
matrix a;
a.ma[0][0] = 1;
a.ma[0][1] = 3;
a.ma[1][0] = 3;
a.ma[1][1] = 8;
for(int i = 1 ;i <= 10 ; i++)
{
matrix tmp = m_pow(a,i);
LL s1 = tmp.ma[0][1] * 3 + tmp.ma[1][1] * 1;
LL b = (s1-1)/2;
LL s2 = tmp.ma[0][0] * 3 + tmp.ma[1][0] * 1;
LL a = s2;
printf("%10.lld%10.lld\n",a,b);
}
return 0;
}
来源:https://www.cnblogs.com/Felix-F/p/3223323.html