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