[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 }

 

posted @ 2017-08-21 13:15  Kirai  阅读(505)  评论(0编辑  收藏  举报