2022.08.27 模拟赛小结

2022.08.27 模拟赛小结

题面

链接

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

更好的阅读体验戳此进入

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

赛时思路

T1

原题是 LOJ-535 「LibreOJ Round #6」花火 ,题意大概是一个序列,然后可以将其中任意两个值调换位置一次,然后再求逆序对个数。

只是求逆序对的话显然 $ O(n log n) $ 随便过,但是加上这个调换位置确实是直接不会了,想了半天也没什么好的思路,最后只能想到枚举+树状数组 $ O(n^3logn) $ 但是显然只能过 $ 30% $,然后写了两行之后就决定干脆 $ O(n^4) $ 做得了,反正得分应该没区别,就没必要多浪费时间了。

然后呢和我预料的差不多,25pts,小点里有一个 WA 了,不知道是哪里寄掉了。

Code:

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

using namespace std;

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

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

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

// struct Tree{
//     int arr[61000];
//     int lim;
//     int lowbit(int x){return x & (-x);}
//     void push(int v){while(x <= lim){arr[x] += x}}
// }
int N;
int a[610000];
int main(){
    freopen("swaq.in", "r", stdin);
    freopen("swaq.out", "w", stdout);
    N = read();
    for(int i = 1; i <= N; ++i)a[i] = read();
    if(N <= 500){
        // int times(0);
        // for(int i = 1; i <= N; ++i){
        //     for(int j = i + 1; j <= N; ++j){
        //         if(i > j)++times;
        //     }
        // }
        // int maxx(0);
        // for(int i = 1; i <= N; ++i){
        //     for(int j = 1; j <= N; ++j){

        //     }
        // }
        int minn = INT_MAX;
        for(int i = 1; i <= N; ++i){
            for(int j = i + 1; j <= N; ++j){
                swap(a[i], a[j]);
                int sum(0);
                for(int k = 1; k <= N; ++k){
                    for(int l = k + 1; l <= N; ++l){
                        if(a[l] < a[k])++sum;
                    }
                }
                // for(int i_ = 1; i_ <= N; ++i_)printf("%d ", a[i_]);
                // printf(" ans is %d\n", sum);
                swap(a[i], a[j]);
                minn = min(minn, sum);
            }
        }
        printf("%d\n", minn + 1);
    }

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

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

T2

原题是 HDU-7262 三角函数(为了方便就给个 vjudge 的链接吧),是一个欧几里得的题,或者说的更准确应该是个更相减损的题,有很多性质然后最后可以转化为更相减损,很考验思维。不过赛时雀食没推出来,用了一些乱搞的做法最终拿到了 10pts,(如果是 NOILinux 评测环境的话有可能会高一点,用到的 __float128 在 MinGW 里会失效)

然后还有一个特别 sb 的错误,我用 __float128 来让精度极高,然后判等的时候 eps 我直接设置的 $ 1 \times 10^{-5} $,直接导致精度太低然后让某些数经过很多次 $ arctan $ 计算后近似相等,我感觉甚至改成 $ 1 \times 10^{-20} $ 应该都行。

回到我的乱搞做法,观察发现输入数据只有两个数,而且部分分范围很低,所以考虑数据库思想自动生成一个大表,用一些奇怪的 BFS,(这题的状态用宽搜确实难搜,我最后用队列里套 pair 套 __float128 和 枚举类型的 vector ),或者迭代加深 DFS 似乎也行???

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

using namespace std;

typedef long long ll;
typedef unsigned long long unll;
typedef long double ld;
typedef unsigned int uint;
typedef __float128 f128;

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

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


#define eps (f128)(1e-5)

bool cmp(f128 a, f128 b){return fabs((double)a - (double)b) <= eps;}
f128 x;
f128 ans;

#define vf vector < func > 

enum func{sinn = 1, coss, atann, out_of_range__};
vf oper;

/*void bfs(int q__){
    double begT = (double)clock() / CLOCKS_PER_SEC;
    queue < pair < f128, vf > > q;
    vf empt;
    q.push(make_pair((f128)0.0, empt));
    while(!q.empty()){
        auto head = q.front(); q.pop();
        // if(cmp(head.first, ans)){
        //     oper = head.second;
        //     return;
        // }
        // if((double)clock() / CLOCKS_PER_SEC >= 0.90)return;
        for(func f = sinn; f <= atann; f = func(f + 1)){

            head.second.push_back(f);
            // printf("current: %.5lf\n", (double)head.first);
            f128 tmp(0.0);
            switch(f){
                case sinn:{
                    tmp = sinf128(head.first);
                    break;
                }
                case coss:{
                    tmp = cosf128(head.first);
                    break;
                }
                case atann:{
                    tmp = atanf128(head.first);
                    break;
                }
                default:{
                    printf("error\n");
                    break;
                }
            }
            if(cmp(tmp, ans)){
                oper = head.second;
                return;
            }
            if((int)head.second.size() > q__ * 2 + 1 || (double)clock() / CLOCKS_PER_SEC >= 0.80){
                printf("None");
                oper.clear();
                return;
            }
            // head.first = tmp;
            q.push(make_pair(tmp, head.second));
            head.second.pop_back();
        }
    }
}


void CAL(int p, int q){
    // fprintf(stderr, "caling p=%d, q=%d\n", p, q);
    oper.clear();
    ans = sqrtf128((f128)p / (f128)q);
    // printf("%.7lf\n%.7lf\n", (double)ans, (double)(sin(atan(cos(0.0)))));
    // printf("else if(p==%d&&q==%d)printf(\"", p, q);
    bfs(q);
    // reverse(oper.begin(), oper.end());
    for(auto i : oper){
        switch(i){
            case sinn:{
                printf("s");
                break;
            }
            case coss:{
                printf("c");
                break;
            }
            case atann:{
                printf("t");
                break;
            }
            default:{
                printf("error\n");
                break;
            }
        }
    }
    // printf("\\n\");\n");
    printf("\n");
    // if(p % 5 == 0 || q % 5 == 0){
    //     printf("\n");
    //     // fprintf(stderr, "Complete p=%d, q=%d\n", p, q);
    //     // fflush(stderr);
    // }
    // fflush(stdout);
}
*/


//这里因为测评用的MinGW,所以我用的__float128会CE,所以只能注释掉了

int main(){
    freopen("luckysct.in", "r", stdin);
    freopen("luckysct.out", "w", stdout);
    int p = read(), q = read();
    if(p==1&&q==1)printf("c\n");
    else if(p==1&&q==2)printf("cts\n");
    else if(p==2&&q==2)printf("c\n");
    else if(p==1&&q==3)printf("ctsts\n");
    else if(p==2&&q==3)printf("ctstc\n");
    else if(p==3&&q==3)printf("c\n");
    else if(p==1&&q==4)printf("ctststs\n");
    else if(p==2&&q==4)printf("cts\n");
	//......
    //剩下的就先删掉了,一大片表

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

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

Build Code: (生成表用的程序)

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


using namespace std;

typedef long long ll;
typedef unsigned long long unll;
typedef long double ld;
typedef unsigned int uint;
typedef __float128 f128;

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

#define eps (f128)(1e-5)

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

bool cmp(f128 a, f128 b){return fabsf128(a - b) <= eps;}
f128 x;
f128 ans;

#define vf vector < func > 

enum func{sinn = 1, coss, atann, out_of_range__};
vf oper;

void bfs(int q__){
    double begT = (double)clock() / CLOCKS_PER_SEC;
    queue < pair < f128, vf > > q;
    vf empt;
    q.push(make_pair((f128)0.0, empt));
    while(!q.empty()){
        auto head = q.front(); q.pop();
        // if(cmp(head.first, ans)){
        //     oper = head.second;
        //     return;
        // }
        // if((double)clock() / CLOCKS_PER_SEC >= 0.90)return;
        for(func f = sinn; f <= atann; f = func(f + 1)){

            head.second.push_back(f);
            // printf("current: %.5lf\n", (double)head.first);
            f128 tmp(0.0);
            switch(f){
                case sinn:{
                    tmp = sinf128(head.first);
                    break;
                }
                case coss:{
                    tmp = cosf128(head.first);
                    break;
                }
                case atann:{
                    tmp = atanf128(head.first);
                    break;
                }
                default:{
                    printf("error\n");
                    break;
                }
            }
            if(cmp(tmp, ans)){
                oper = head.second;
                return;
            }
            if((int)head.second.size() > q__ * 2 + 1 || (double)clock() / CLOCKS_PER_SEC - begT >= 5.00){
                printf("None");
                oper.clear();
                return;
            }
            // head.first = tmp;
            q.push(make_pair(tmp, head.second));
            head.second.pop_back();
        }
    }
}


void CAL(int p, int q){
    fprintf(stderr, "caling p=%d, q=%d\n", p, q);
    oper.clear();
    ans = sqrtf128((f128)p / (f128)q);
    // printf("%.7lf\n%.7lf\n", (double)ans, (double)(sin(atan(cos(0.0)))));
    printf("else if(p==%d&&q==%d)printf(\"", p, q);
    bfs(q);
    // reverse(oper.begin(), oper.end());
    for(auto i : oper){
        switch(i){
            case sinn:{
                printf("s");
                break;
            }
            case coss:{
                printf("c");
                break;
            }
            case atann:{
                printf("t");
                break;
            }
            default:{
                printf("error\n");
                break;
            }
        }
    }
    printf("\\n\");\n");
    // if(p % 5 == 0 || q % 5 == 0){
    //     printf("\n");
    //     // fprintf(stderr, "Complete p=%d, q=%d\n", p, q);
    //     // fflush(stderr);
    // }
    fflush(stdout);
}
bool check(int p, int q){
    for(int i = 2; i * i <= min(p, q); ++i){
        if(p % i == 0 && q % i == 0)return false;
    }
    return true;
}


int main(){
    // int p = read(), q = read();
    
    // printf("\n");
    //     fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    freopen("/home/jdoi/cpp/OI/Exams/Monkey/luckysct/build.txt", "w", stdout);
    for(int q = 10; q <= 1000; ++q){
        for(int p = 1; p <= q; ++p){
            if(check(p, q))CAL(p, q);
        }
    }



    return 0;
}

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

T3

一个我感觉挺离谱的整体二分+树形 DP,思路奇奇怪怪,赛时我是没想出来,不过给的几个特殊性质点还是非常容易就能想到的。

然后考虑暴力我不会写不好写,所以想到了个很奇怪的贪心,大概就是考虑只删 dist 相同的一层,然后显然能删的数量和 dist 相同,排序之后找对应的第 dist 大的数,简而言之就是个很奇怪的乱搞(我都不知道怎么想到的),不过最后居然对了好几个点,直接 35pts。

Code:

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

using namespace std;

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

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


#define int ll

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



int N;

struct Edge{
    Edge* nxt;
    // int val;
    int to;
    void* operator new(size_t);
    Edge(Edge* nxt, int to):nxt(nxt), to(to){;}
    Edge(void) = default;
}eData[210000];
void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}
Edge* head[210000];
int deg[210000], val[210000];
int maxdeg(0);
const int root(1);

int dist[210000];

vector < int > nums[210000];

int maxdist(0);
void dfs_dist(int p){
    
    for(auto i = head[p]; i; i = i->nxt){
        dist[i->to] = dist[p] + 1;
        dfs_dist(i->to);
        nums[dist[i->to]].push_back(val[i->to]);
        maxdist = max(maxdist, dist[i->to]);
    }
}

signed main(){
    freopen("ssq.in", "r", stdin);
    freopen("ssq.out", "w", stdout);
    N = read();
    for(int i = 2; i <= N; ++i)val[i] = read();
    for(int i = 1; i <= N - 1; ++i){
        int f = read(), t = read();
        head[f] = new Edge(head[f], t);
        deg[f]++, deg[t]++;
        maxdeg = max(maxdeg, max(deg[f], deg[t]));
    }
    if(deg[1] == 1 && maxdeg <= 2){
        printf("0\n");
        return 0;
    }
    if(deg[1] <= 2 && maxdeg <= 2){
        int ans(0);
        for(auto i = head[1]; i; i = i->nxt){
            ans = max(ans, val[i->to]);
        }
        printf("%lld\n", ans);
        return 0;
    }
    int ans(0);
    dfs_dist(1);
    for(int i = 1; i <= maxdist; ++i){
        if(nums[i].size() <= i)continue;
        sort(nums[i].begin(), nums[i].end(), greater<int>());
        ans = max(ans, nums[i].at(i));
    }
    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);
    T flag(1);
    char c = getchar();
    while(!isdigit(c) && 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

大概是做的最崩的一道题,首先写这题的时候人已经困傻了,大概梦游了 0.5~1.0h 然后开始写,最后开始写暴力,然后就是没写出来,感觉题意都没完全理解,所以最后无奈直接写了个输出 rand(),然后不出所料 0pts。

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

using namespace std;

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

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

#define MOD 998244353


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

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


int N, M;
int atk[11000], def[11000];
int pos[11000], l[11000], r[11000];

int cnt(0);

vector < int > opt;

bool vis[110000];
bool used[110000];

void explode(int x, int w){
    if(!used[x] && w > def[x]){
        if(x != 1 && !used[x - 1]){
            used[x - 1] = true;
            vis[x - 1] = true;
            explode(x - 1, atk[x] - l[x]);
        }
        if(x != N && !used[x + 1]){
            used[x + 1] = true;
            vis[x + 1] = true;
            explode(x + 1, atk[x] - r[x]);
        }
    }
} 
bool check(){
    
    memset(vis, false, sizeof(vis));
    for(auto i : opt){
        memset(used, false, sizeof(used));
        explode(pos[i], INT_MAX);
    }
    for(int i = 1; i <= N; ++i){
        if(!vis[i])return false;
    }
    return true;
}
void dfs(int dep){
    if(dep > M){
        if(check())++cnt;
        return;
    }
    dfs(dep + 1);
    opt.push_back(dep);
    dfs(dep + 1);
    opt.pop_back();
}





int main(){
    freopen("dota.in", "r", stdin);
    freopen("dota.out", "w", stdout);
    int T = read();
    while(T--){
        cnt = 0;
        N = read(), M = read();
        for(int i = 1; i <= N; ++i)atk[i] = read(), def[i] = read();
        for(int i = 1; i <= M; ++i)pos[i] = read(), l[i] = read(), r[i] = read();
        // dfs(1);
        //  printf("%d\n", cnt);
        printf("%d\n", rndd(1, 315));
    }
   

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

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

正解

T2

这题我挺喜欢,单独写一个 Blog 吧,戳此进入

T1

咕咕咕

T3

咕咕咕

T4

咕咕咕

UPD

update-2022_8_27 初稿

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