2022.09.13 模拟赛小结

2022.09.13 模拟赛小结

题面

PDF链接

(这个链接只是为了自己方便找,页面设置权限了,不要尝试访问)

更好的阅读体验戳此进入

(建议您从上方链接进入我的个人网站查看此 Blog,在 Luogu 中图片会被墙掉,部分 Markdown 也会失效)

赛时思路

T1

原题 LG-P1772 [ZJOI2006] 物流运输

是一道 DP + 最短路,赛时没想到 DP,嗯写了个 Dijk + 随机化微小扰动 + 卡时,当然最后寄掉了。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define npt nullptr

/******************************
abbr

******************************/

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int percent){return rndd(1, 100) <= percent;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;

bitset < 110 > wharf[22];
int blocked[22];

template<typename T = int>
inline T read(void);

struct Edge{
    Edge* nxt;
    int to;
    int val;
    void* operator new(size_t);
    Edge(Edge* nxt, int to, int val):nxt(nxt), to(to), val(val){;}
    Edge(void) = default;
}eData[410];
void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}
Edge* head[22];

int N, M, K, E;

bool vis[22];
ll dis[22];
void Dijk(int);

priority_queue < 
    pair < ll, int > /*distance, vertex*/,
    vector < pair < ll, int > >,
    // [](pair < int, int > x, pair < int, int > y) ->bool{
    // }
    greater < pair < ll, int > >
 > vert;
int main(){
    freopen("plan.in", "r", stdin);
    freopen("plan.out", "w", stdout);
    N = read(), M = read(), K = read(), E = read();
    for(int i = 1; i <= E; ++i){
        int f = read(), t = read(), val = read();
        if(f == t)continue;
        head[f] = new Edge(head[f], t, val);
        head[t] = new Edge(head[t], f, val);
    }
    int D = read();
    while(D--){
        int p = read(), a = read(), b = read();
        for(int i = a; i <= b; ++i)wharf[p][i] = true;
    }
    for(int i = 1; i <= M; ++i)blocked[i] = wharf[i]._Find_next(0);
    ll ans(0);
    ll lastcost(-1);
    for(int i = 1; i <= N; ++i){
        Dijk(i);
        ll cost = dis[M];
        ans += cost;
        if(i != 1 && cost != lastcost)ans += K;
        lastcost = cost;
    }
    while((double)clock() / CLOCKS_PER_SEC < 0.7){
        for(int i = 1; i <= M; ++i){
            for(auto j = head[i]; j; j = j->nxt){
                if(rnddd(10))j->val *= 1.05;
            }
            blocked[i] = wharf[i]._Find_next(0);
        }
        ll anss(0);
        ll lastcostt(-1);
        for(int i = 1; i <= N; ++i){
            Dijk(i);
            ll costt = dis[M];
            anss += costt;
            if(i != 1 && costt != lastcostt)anss += K;
            lastcostt = costt;
        }
        ans = min(ans, anss);
    }
    printf("%lld\n", ans);
    // fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}


void Dijk(int day){
    bool block[22];
    memset(block, false, sizeof(block));
    for(int i = 1; i <= M; ++i){
        if(day == blocked[i]){
            block[i] = true;
            if(blocked[i] <= N)blocked[i] = wharf[i]._Find_next(blocked[i]);
        }
    }
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= M; ++i)dis[i] = LLONG_MAX / 2ll - 10ll;
    dis[1] = 0ll;
    vert.push(make_pair(dis[1], 1));
    while(!vert.empty()){
        int p;
        tie(ignore, p) = vert.top();
        vert.pop();
        if(vis[p] || block[p])continue;
        vis[p] = true;
        for(auto i = head[p]; i; i = i->nxt){
            if(dis[p] + i->val < dis[i->to]){
                dis[i->to] = dis[p] + i->val;
                if(!vis[i->to])vert.push(make_pair(dis[i->to], i->to));
            }
        }
    }
}

template<typename T>
inline T read(void){
    T ret(0);
    short flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

/*

5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5

*/

T2

原题是 LG-P1768 天路

赛时写了个 $ n $ 次 Dijkstra,然后还是重载的一大堆符号,似乎假掉了,Luogu 上过了一个点其他全部 RE,数据下不了暂时不知道什么原因。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define npt nullptr

/******************************
abbr

******************************/

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;

template<typename T = int>
inline T read(void);

struct Node{
    int v, p;
    Node(int v, int p):v(v), p(p){;}
    Node(void) = default;
    bool operator < (const Node d)const{/////////////////////
        if(!this->p || !this->v)return true;
        if(!d.p || !d.v)return false;
        double x = (double)this->v / (double)this->p;
        double y = (double)d.v / (double)d.p;
        return x < y;
    }
    bool operator > (const Node d)const{/////////////////////
        if(!this->p || !this->v)return false;
        if(!d.p || !d.v)return true;
        double x = (double)this->v / (double)this->p;
        double y = (double)d.v / (double)d.p;
        return x > y;
    }
    Node operator + (Node d){
        return Node(this->v + d.v, this->p + d.p);
    }
    void operator = (Node d){
        this->p = d.p;
        this->v =d.v;
    }
};

struct Edge{
    Edge* nxt;
    int to;
    Node val;
    void* operator new(size_t);
    Edge(Edge* nxt, int to, Node val):nxt(nxt), to(to), val(val){;}
    Edge(void) = default;
}eData[21000];
void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}
Edge* head[7500];

int N, M;

bool vis[22];
Node dis[22];
void Dijk(int);



priority_queue < 
    pair < Node, int >/*value, vertex*/,
    vector < pair < Node, int > >,
    less < pair < Node, int > >
> vert;

int main(){
    freopen("road.in", "r", stdin);
    freopen("road.out", "w", stdout);
    N = read(), M = read();
    for(int i = 1; i <= M; ++i){
        int f = read(), t = read(), v = read(), p = read();
        if(f == t)continue;
        head[f] = new Edge(head[f], t, Node(v, p));
    }
    Node ans(0, 0);
    for(int i = 1; i <= N; ++i){
        Dijk(i);
        if(dis[i] > ans)ans = dis[i];
        // printf("No.%d  %.3lf\n", i, (double)dis[i].v / (double)dis[i].p);
    }
    if(!ans.v || !ans.p)printf("-1\n");
    else printf("%.1lf\n", (double)ans.v / (double)ans.p);

    // fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}


void Dijk(int S){
    memset(vis, false, sizeof(vis));
    // memset(dis, 0x3f, sizeof(dis));
    for(int i = 1; i <= N; ++i)dis[i].v = 0, dis[i].p = 0x3f3f3f3f;
    dis[S] = Node(0, 0);
    vert.push(make_pair(dis[S], S));
    while(!vert.empty()){
        int p;
        tie(ignore, p) = vert.top();
        vert.pop();
        if(vis[p])continue;
        vis[p] = true;
        if(p == S)vis[p] = false;
        for(auto i = head[p]; i; i = i->nxt){
            if(dis[p] + i->val > dis[i->to]){
                dis[i->to] = dis[p] + i->val;
                if(!vis[i->to])vert.push(make_pair(dis[i->to], i->to));
            }
        }
    }
}

template<typename T>
inline T read(void){
    T ret(0);
    short flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

/*

5 6
1 2 1 1
4 1 6 2
5 4 8 1
2 3 2 2
5 2 4 1
3 5 6 4

*/

T3

原题是:CF510D Fox And Jumping

差为 1 即可全部覆盖的性质找到了,但是裴蜀定理不太熟悉,没给它转化为 gcd 为 1,所以最后只能打了个暴力。

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr

/******************************
abbr

******************************/

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;

#define int ll

template<typename T = int>
inline T read(void);

int N;
int len[310], pri[310];
ll ans(LLONG_MAX);
void bfs(){
    queue < pair < int, int > >q;
    q.push(make_pair(0, 0));
    while(!q.empty()){
        int cur, cpri;
        tie(cur, cpri) = q.front();
        q.pop();
        if(cur == 1){
            ans = min(ans, cpri);
        }
        for(int i = 1; i <= N; ++i){
            q.push(make_pair(cur + len[i], cpri + pri[i]));
            q.push(make_pair(cur - len[i], cpri + pri[i]));
        }
        if((double)clock() / CLOCKS_PER_SEC > 1.8){
            if(ans == LLONG_MAX)printf("-1\n");
            else printf("%lld\n", ans);
            exit(0);
        }
    }
}
signed main(){
    freopen("jump.in", "r", stdin);
    freopen("jump.out", "w", stdout);
    N = read();
    for(int i = 1; i <= N; ++i)len[i] = read();
    for(int i = 1; i <= N; ++i)pri[i] = read();
    // int dep(0);
    bfs();
    // printf("%lld\n", ans);
    // fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}



template<typename T>
inline T read(void){
    T ret(0);
    short flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

T4

原题是:HDU 6611 K Subsequence

我不会

正解

T1

还挺显然的,简单改了一下没过,咕咕咕

T2

大概是二分答案然后 SPFA 找环,emmmm,这个找时间再弄一下,SPFA 没怎么写过,暂时先咕掉。

T3

正解是状压 DP,因为质因数最多好像就八个。不过这道题可以用 map 优化直接切掉,并且复杂度似乎还是正确的。。。

T4

拆点 + 费用流,挺难我不会,还得再看看费用流。

UPD

update-2022_09_13 初稿

posted @ 2022-09-20 10:53  Tsawke  阅读(30)  评论(0编辑  收藏  举报