poj3233 矩阵等比数列求和 二分
对于数列S(n) = a + a^2 + a^3 +....+ a^n;
可以用二分的思想进行下列的优化。
if(n & 1)
S(n) = a + a^2 + a^3 + ....... + a^n;
= a + a^2 + a^3 +..+ a^((n-1) / 2) + a^((n-1) / 2 + 1) + a^((n-1) / 2 + 2) + ... + a^((n-1) / 2 + (n-1) / 2) + a^((n-1) / 2 + (n-1) / 2 + 1);
= (1 + a^((n-1) / 2 + 1)) * S((n-1)/2) + a^((n-1) / 2 + 1)
else
S(n) = a + a^2 + a^3 + ....... + a^n;
= a + a^2 + a^3 +..+ a^((n / 2) + a^(n / 2 + 1) + a^(n / 2 + 2) + ... + a^(n/ 2 + n / 2);
= (1 + a^(n / 2)) * S(n / 2);
这样就可以避免矩阵的除法了! 还有就是MOD真的很慢。
#include<map> #include<set> #include<string> #include<queue> #include<stack> #include<cmath> #include<vector> #include<cstdio> #include<time.h> #include<cstring> #include<iostream> #include<algorithm> #define INF 1000000001 #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int MAXN = 100010; struct Mat { ll a[45][45]; }E; int n,k,MOD; Mat Matadd(Mat a,Mat b) { Mat c; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ c.a[i][j] = (a.a[i][j] + b.a[i][j])%MOD; } } return c; } Mat Matmul(Mat a,Mat b) { Mat c; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ c.a[i][j] = 0; for(int k = 0; k < n; k++){ c.a[i][j] += (a.a[i][k] * b.a[k][j])%MOD; } c.a[i][j] %= MOD; } } return c; } Mat power(Mat a,int n) { Mat c; c = E; while(n){ if(n & 1){ c = Matmul(c,a); } a = Matmul(a,a); n >>= 1; } return c; } Mat sum(Mat a,int k)//求S(k) { if(k == 1)return a; Mat t = sum(a,k/2);//S(k/2) if(k & 1){ Mat cur = power(a,k/2 + 1);//a^(k/2 + 1) t = Matadd(t,Matmul(t,cur));//(1 + a^(k/2+1))*S(k/2) t = Matadd(t,cur);//(1 + a^(k/2 + 1))*S(k/2) } else { Mat cur = power(a,k/2);//a^(k/2) t = Matadd(t,Matmul(t,cur));//(1 + a^(k/2))*S(k/2) } return t; } int main() { while(scanf("%d%d%d",&n,&k,&MOD) != EOF){ Mat a; memset(E.a,0,sizeof(E.a)); for(int i = 0; i < n; i++)E.a[i][i] = 1; for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ scanf("%lld",&a.a[i][j]); a.a[i][j] %= MOD; } } Mat ans = sum(a,k); for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ if(j == 0)printf("%lld",ans.a[i][j]); else { printf(" %lld",ans.a[i][j]); } } printf("\n"); } } return 0; }