ペトロザヴォーツク冬のトレーニングキャンプ2017G(スタック)問題への解決策

質問の意味:

\(M_I \)\(M * Mの\)行列、公知
\ [\ {整列}始める& M_0 = A \\&M_I =(\ prod_ {J = C_I} ^ {I + 1} M_j)B \ 端{整列} \]
Q \(M_n \)行列、入力含む\を(N、M、A、B、C_1と\ cdots C_N(C_1および\のLeq C_2 \ cdots \ C_N 1当量)\)

アイデア:

以来\(C_1 \のLeq C_2 \ cdots \のLeq C_N \)ので、我々は唯一のヘッドからチームを満たすためにキューを実装する必要があります\(POP \)をテールから、\(プッシュ\) およびキュー内の製品を見つけることができます。これは、2つのスタックで達成することができます。
スタック\(SUF \)保存された製品の接尾辞で、\は(前\)保存され、その後、接頭辞の製品です\(プッシュ\)それが置かれたとき(前\)\維持し、製品のプレフィックスが行列に入る格納する\ (\ポップ)する場合、直接(SUF \)\サフィックスポップ缶の前に。場合は\(SUFの\)が空であるので、\(前\)暴力への接尾辞ではなり\(SUF \)の内側。各マトリックスは、2つの最大値にスタックを知ることができ、複雑\(O(NM ^ 2)\)

コード:

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<bitset>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const ll MOD = 1000000007;
struct Mat{
    int s[5][5];
    void init(){memset(s, 0, sizeof(s));}
};
int n, m, mod;
int ksc(ll a, ll b, ll p){
    ll t = a * b - (ll)((long double)a * b / p + 0.5) * p;
    t = (t < 0)? t + p : t;
    return (int)t;
}
inline Mat mul(Mat a, Mat b){
    Mat c;
    c.init();
    for(int i = 0; i < m; i++){
        for(int j = 0; j < m; j++){
            for(int k = 0; k < m; k++){
                c.s[i][j] = (c.s[i][j] + ksc(a.s[i][k], b.s[k][j], mod)) % mod;
            }
        }
    }
    return c;
}
Mat pre[maxn], suf[maxn], a[maxn];
int cnt1, cnt2, c[maxn];
void ins(Mat x){
    if(cnt1 == 0) pre[++cnt1] = x;
    else{
        pre[++cnt1] = x;
        pre[cnt1] = mul(pre[cnt1 - 1], x);
    }
    a[cnt1] = x;
}
void del(){
    if(cnt2 == 0){
        for(int i = cnt1; i >= 1; i--){
            if(cnt2 == 0) suf[++cnt2] = a[i];
            else suf[++cnt2] = a[i], suf[cnt2] = mul(suf[cnt2], suf[cnt2 - 1]);
        }
        cnt1 = 0;
    }
    cnt2--;
}
int main(){
    while(~scanf("%d%d%d", &n, &m, &mod)){
        cnt1 = cnt2 = 0;
        Mat A, B, ret;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < m; j++){
                scanf("%d", &A.s[i][j]);
            }
        }
        for(int i = 0; i < m; i++){
            for(int j = 0; j < m; j++){
                scanf("%d", &B.s[i][j]);
            }
        }
        for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
        int L = 0;
        ins(A);
        for(int i = 1; i <= n; i++){
            while(L < c[i]) del(), L++;
            if(cnt1 && cnt2) ret = mul(suf[cnt2], pre[cnt1]);
            else if(cnt1) ret = pre[cnt1];
            else ret = suf[cnt2];
            ret = mul(ret, B);
            ins(ret);
        }
        for(int i = 0; i < m; i++){
            for(int j = 0; j < m; j++){
                printf("%d%c", ret.s[i][j], j == m - 1? '\n' : ' ');
            }
        }
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/KirinSB/p/11618353.html