LightOJ 1070 - Algebraic Problem 矩阵高速幂
题链:http://lightoj.com/volume_showproblem.php?problem=1070
Time Limit: 2 second(s) | Memory Limit: 32 MB |
Given the value of a+b and ab you will have to find the value of an+bn. a and b not necessarily have to be real numbers.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains three non-negative integers, p, q and n. Here p denotes the value of a+b and q denotes the value of ab. Each number in the input file fits in a signed 32-bit integer. There will be no such input so that you have to find the value of 00.
Output
For each test case, print the case number and (an+bn) modulo 264.
Sample Input |
Output for Sample Input |
2 10 16 2 7 12 3 |
Case 1: 68 Case 2: 91 |
给你p=a+b, q=ab
算出 (a^n+b^)mod2^64
做法:
mod 2^64所以开 unsigned long long 。llu 即可了,达到上限会自己主动取模的。
然后就是公式了。我是在推公式中找到的规律。
a^2+b^2=(a+b)*(a+b)-2*a*b
a^3+b^3=(a^2+b^2)*(a+b)-a*b(a+b)
a^4+b^4=(a^3+b^3)*(a+b)-a*b(a^2+b^2)
设G(n)=a^n+b^n
G(n)=G(n-1)*p-G(G-2)*q
然后就是高速幂了。.
#include<stdio.h> #include<string.h> #define Matr 5 //矩阵大小,注意能小就小 矩阵从1開始 所以Matr 要+1 最大能够100 #define ll unsigned long long struct mat//矩阵结构体。a表示内容,size大小 矩阵从1開始 但size不用加一 { ll a[Matr][Matr]; mat()//构造函数 { memset(a,0,sizeof(a)); } }; int Size= 2; mat multi(mat m1,mat m2)//两个相等矩阵的乘法,对于稀疏矩阵,有0处不用运算的优化 { mat ans=mat(); for(int i=1;i<=Size;i++) for(int j=1;j<=Size;j++) if(m1.a[i][j])//稀疏矩阵优化 for(int k=1;k<=Size;k++) ans.a[i][k]=(ans.a[i][k]+m1.a[i][j]*m2.a[j][k]); //i行k列第j项 return ans; } mat quickmulti(mat m,ll n)//二分高速幂 { mat ans=mat(); int i; for(i=1;i<=Size;i++)ans.a[i][i]=1; while(n) { if(n&1)ans=multi(m,ans);//奇乘偶子乘 挺好记的. m=multi(m,m); n>>=1; } return ans; } void print(mat m)//输出矩阵信息。debug用 { int i,j; printf("%d\n",Size); for(i=1;i<=Size;i++) { for(j=1;j<=Size;j++) printf("%llu ",m.a[i][j]); printf("\n"); } } int main() { /* ll a,b; while(scanf("%llu",&a)!=EOF) printf("%llu\n",-a+18446744073709551615+1); */ int t; int cas=1; scanf("%d",&t); while(t--) { ll p,q,n; int p1,q1; scanf("%lld%lld%llu",&p,&q,&n);// p a+b q ab ll tem=18446744073709551615-q+1; mat gouzao=mat(),chu=mat();//构造矩阵 初始矩阵 chu.a[1][1]=p; chu.a[1][2]=p*p+2*tem; chu.a[1][3]=q; printf("Case %d: ",cas++); if(n==0) printf("2\n"); else if(n==1) printf("%llu\n",p); else if(n==2) printf("%llu\n",p*p+2*tem); else { gouzao.a[1][1]=0; gouzao.a[2][1]=1; gouzao.a[1][2]=tem; gouzao.a[2][2]=p; //print(gouzao); printf("%llu\n",multi(chu,quickmulti(gouzao,n-2)).a[1][2]); } } return 0; } /* ans^=n - mat ans=mat(); ans.size=Size; 初始化ans矩阵 ans=quickmulti(ans,n,mod); void print(mat m)//输出矩阵信息。debug用 { int i,j; printf(%dn,m.size); for(i=1;i=m.size;i++) { for(j=1;j=m.size;j++)printf(%d ,m.a[i][j]); printf(n); } } */