这题给出a+b,a*b,让你求a^n+b^n。
第一直觉肯定是求出a和b,然后直接暴力求解。但是这里就有两个问题了。
一个是精度的浪费,当n很大的时候,如果a和b是小数,那就会带来很大的精度浪费,最终导致答案的错误。
第二个就是,可能这样的a和b是复数。
所以可以考虑利用递推求解。
(a^n+b^n)*(a+b)=a^(n+1)+b^(n+1)+ab*(a^(n-1)+b^(n-1))
我们令fn=a^n+b^n,那么我们有:fn*(a+b)=f(n+1)+ab*f(n-1)。
那么我们就能构造出矩阵,利用快速幂解决。。。不得不说这题的输入有点坑,详细请看程序。
#include <iostream> #include <cstdio> #include <cstring> #define MAX 5 using namespace std; typedef long long i64; i64 a[MAX][MAX], b[MAX][MAX], c[MAX][MAX], buff[MAX][MAX], vec[MAX]; void matCpy(i64 a[MAX][MAX], i64 b[MAX][MAX], int n) { int i, j; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { a[i][j] = b[i][j]; } } } void norm(i64 a[MAX][MAX], int n) { int i, j; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { a[i][j] = (i == j); } } } void matMul(const i64 a[MAX][MAX], const i64 b[MAX][MAX], i64 c[MAX][MAX], int n) { int i, j, k; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { for (c[i][j] = k = 0; k < n; ++k) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]); } } } } void matPow(i64 a[MAX][MAX], i64 b, i64 c[MAX][MAX], int n) { for (norm(c, n); b; b >>= 1) { if (b & 1) { matMul(c, a, buff, n); matCpy(c, buff, n); } matMul(a, a, buff, n); matCpy(a, buff, n); } } int main(){ i64 p,q,n; while(cin>>p>>q>>n){ if(n==0) { printf("2\n"); continue; } if(n==1) { printf("%lld\n",p); } else { a[0][0]=p,a[0][1]=-q; a[1][0]=1,a[1][1]=0; matPow(a,n-1,b,2); //printf("%lld %lld\n",b[0][0],b[0][1]); printf("%lld\n",b[0][0]*p+b[0][1]*2); } } return 0; }
UVA 10655 Contemplation! Algebra
最新推荐文章于 2020-02-07 11:05:28 发布