Submission #316585

#TimeUsernameProblemLanguageResultExecution timeMemory
316585ehab_fawzyEnergetic turtle (IZhO11_turtle)C++14
100 / 100
931 ms6136 KiB
//#pragma GCC optimize ("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define F first
#define S second
#define pb push_back
#define ll long long
#define all(x) x.begin() , x.end()
#define rep(i,s,e) for (int i = s; i < e; ++i)
#define rev(i,s,e) for (int i = s; i > e; --i)
#define mem(a,v) memset(a , v , sizeof a)
#define negmod(x,m) ((x%m + m)%m)
template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,
        tree_order_statistics_node_update>;

const int N = 25 , M = 7e5 + 9;

ll n , m , k , t, mod , paths[N][N];
vector<pair<ll,ll>> points;

ll add( ll x , ll y ){
    ll ret = x + y;
    while ( ret >= mod ) ret -= mod;
    while ( ret <  0   ) ret += mod;
    return ret;
}
ll mul( ll x , ll y ){
    ll ret = x * y;
    if ( ret >= mod ) ret %= mod;
    if ( ret <  0   ) ret  = negmod(ret , mod);
    return ret;
}

inline ll pwr( ll x , ll y ){
    if ( y == 0 ) return mul(1 , 1);
    if ( y == 1 ) return mul(x , 1);
    return mul( (y&1 ? x : 1) , pwr( mul(x,x) , y >> 1 ) );
}

int pr[M] , comp[M] , ptr;
void linear_sieve() {
    for (int i = 2; i < M; ++i) {
        if (!comp[i]) pr[ptr++] = i , comp[i] = i;
        rep(j, 0, ptr) {
            ll mul = 1LL * i * pr[j];
            if (mul > M) break;
            comp[mul] = pr[j];
            if (i % pr[j] == 0) break;
        }
    }
}

int factorsCnt[M] , lst[M] , itr;
ll pCr( ll P , ll R ){
    if ( P < R ) return 0;
    if ( P < 0 or R < 0 ) return 0;
    itr = 0; ll df = P - R , cur;
    for ( int i = P; i > 1; --i ){
        cur = i;
        while ( cur > 1 ){
            if ( factorsCnt[comp[cur]]++ == 0 )
                lst[itr++] = comp[cur];
            cur /= comp[cur];
        }
    }
    int scale ;
    for ( int i = max(R , df); i > 1; --i ){
        scale = (i <= R) + (i <= df); cur = i;
        while ( cur > 1 ){
            factorsCnt[comp[cur]] -= scale;
            cur /= comp[cur];
        }
    }

    ll ans = 1;
    while ( ~--itr ){
        if ( factorsCnt[lst[itr]] > 0 ){
            ans = mul(ans , pwr(lst[itr] , factorsCnt[lst[itr]])) ;
        }
        factorsCnt[lst[itr]] = 0;
    }
    return ans ;
}

ll pathsCnt( int i , int j ){
    ll X = points[j].F - points[i].F + 1;
    ll Y = points[j].S - points[i].S + 1;
    ll P = X + Y - 2 , R = X - 1;
    return pCr(P , R);
}

ll dp[N][N][N];

int main() {
//    freopen("turtle.in"  , "r" , stdin );
//    freopen("turtle.out" , "w" , stdout);
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifdef CLion
    freopen("input.txt" , "r" , stdin);
//    freopen("output.txt", "w" , stdout);
#endif

    linear_sieve();
    cin >> n >> m >> k >> t >> mod;
    rep(i,0,k){
        int x , y;
        cin >> x >> y;
        points.pb({x , y});
    }
    points.pb({0 , 0});
    points.pb({n , m});
    sort( all(points) );
    k = points.size();

    for ( int i = 0; i < k; ++i ){
        for ( int j = i + 1; j < k; ++j ){
            paths[i][j] = pathsCnt(i , j);
        }
    }

    for ( int i = 0; i < k; ++i ){
        for ( int j = i + 1; j < k; ++j ){
            dp[i][j][0] = paths[i][j];
            for ( int p = i + 1; p < j; ++p ){
                if ( points[p].S >= points[i].S and points[p].S <= points[j].S ){
                    dp[i][j][0] = add( dp[i][j][0] , -mul(dp[i][p][0] , paths[p][j]) );
                }
            }
        }
    }

    ll ans = dp[0][k - 1][0];
    for ( int steps = 1; steps <= t; ++steps ){
        for ( int i = 0; i < k; ++i ){
            for ( int j = i + 1; j < k; ++j ){
                for ( int p = i + 1; p < j; ++p ){
                    if ( points[p].S >= points[i].S and points[p].S <= points[j].S ){
                        dp[i][j][steps] = add( dp[i][j][steps] , mul(dp[i][p][0] , dp[p][j][steps - 1]) );
                    }
                }
            }
        }
        ans = add(ans , dp[0][k - 1][steps] );
    }

    cout << ans ;
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...