[HIHO1555] 四次方根(递推,容斥,矩阵快速幂)
题目链接:http://hihocoder.com/problemset/problem/1555
首先要知道一元四次方程根与系数的关系:
设x^4+ax^3+bx²+cx+d=0的四个根是x1,x2,x3,x4,则
x1+x2+x3+x4=﹣a
x1x2+x1x3+x1x4+x2x3+x2x4+x3x4=b
x1x2x3+x1x2x4+x1x3x4+x2x3x4=﹣c
x1x2x3x4=d
设f(n)=x1^n+x2^n+x3^n+x4^n。
容斥一下就能找到一个递推关系:
f(n)=(x1+x2+x3+x4)*f(n-1)-(x1x2+x1x3+x1x4+x2x3+x2x4+x3x4)*f(n-2)+(x1x2x3+x1x2x4+x2x3x4)*f(n-3)-(x1x2x3x4)*(fn-4)。
整理得:f(n)=-af(n-1)-bf(n-2)-cf(n-3)-df(n-4)。
初始值是这样的:显然f(0)=4,f(1)=-a,f(2)可以由f(1)的结果推过来,展开(x1+x2+x3+x4)^2后,使用上述关系,把f(2)以外的式子减掉,可以得f(2)=a*a-2*b,同理f(3)=f(1)*f(2)+a*b-3*c。
构造四阶矩阵:
-a -b -c -d 1 0 0 0 0 1 0 0 0 0 1 0
负数模运算要注意,先+mod变成正数。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL mod = 1e9+7; 6 const int maxn = 100; 7 8 typedef struct Matrix { 9 LL m[maxn][maxn]; 10 int r, c; 11 Matrix(){ 12 r = c = 0; 13 memset(m, 0, sizeof(m)); 14 } 15 } Matrix; 16 Matrix mul(Matrix m1, Matrix m2, LL mod) { 17 Matrix ans = Matrix(); 18 ans.r = m1.r; ans.c = m2.c; 19 for(int i = 1; i <= m1.r; i++) { 20 for(int j = 1; j <= m2.r; j++) { 21 for(int k = 1; k <= m2.c; k++) { 22 if(m2.m[j][k] == 0) continue; 23 ans.m[i][k] = (ans.m[i][k] + (m1.m[i][j] * m2.m[j][k]) % mod) % mod; 24 } 25 } 26 } 27 return ans; 28 } 29 Matrix quickmul(Matrix m, LL n, LL mod) { 30 Matrix ans = Matrix(); 31 for(int i = 1; i <= m.r; i++) ans.m[i][i] = 1; 32 ans.r = m.r; 33 ans.c = m.c; 34 while(n) { 35 if(n & 1) ans = mul(m, ans, mod); 36 m = mul(m, m, mod); 37 n >>= 1; 38 } 39 return ans; 40 } 41 42 LL n,a,b,c,d; 43 44 signed main() { 45 // freopen("in", "r", stdin); 46 int T; 47 LL f[11]; 48 scanf("%d", &T); 49 while(T--) { 50 scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&d); 51 f[0] = 4LL; 52 f[1]=-a; 53 f[2]=-2LL*b%mod-1LL*a*f[1]%mod; 54 f[3]=-3LL*c%mod-1LL*b*f[1]%mod-1LL*a*f[2]%mod; 55 f[4]=-4LL*d%mod-1LL*c*f[1]%mod-1LL*b*f[2]%mod-1LL*a*f[3]%mod; 56 f[1]=(mod+f[1]%mod)%mod;f[2]=(mod+f[2]%mod)%mod;f[3]=(mod+f[3]%mod)%mod;f[4]=(mod+f[4]%mod)%mod; 57 Matrix p; p.r = p.c = 4; 58 p.m[1][1] = (-a+mod)%mod; p.m[1][2] = (-b+mod)%mod; 59 p.m[1][3] = (-c+mod)%mod; p.m[1][4] = (-d+mod)%mod; 60 p.m[2][1] = 1; p.m[3][2] = 1; p.m[4][3] = 1; 61 if(n <= 4) { 62 printf("%lld\n", f[n]); 63 continue; 64 } 65 p = quickmul(p, n-4, mod); 66 LL ret = 0; 67 for(int i = 1; i <= 4; i++) { 68 ret += p.m[1][i]*f[4-i+1]%mod; 69 ret %= mod; 70 } 71 printf("%lld\n", ret); 72 } 73 return 0; 74 }