8.11 2020 Multi-University Training Contest 7题解及补题

8.11 2020 Multi-University Training Contest 7题解及补题

比赛过程

这场1009签到还可以,很可惜没有做出第二个题,1010其实有些思路,没有写出来,码力弱

题解

A

题意

解法

代码

//将内容替换成代码

B

题意

解法

代码

//将内容替换成代码

C

题意

解法

代码

//将内容替换成代码

D

题意

解法

代码

//将内容替换成代码

E

题意

解法

代码

//将内容替换成代码

F

题意

解法

代码

//将内容替换成代码

G

题意

解法

代码

//将内容替换成代码

H

题意

解法

代码

//将内容替换成代码

I Increasing and Decreasing

题意

输入n,x,y三个数,能否构造一个长度为n的全排列,使得最长上升子序列的长度为x,最长下降子序列的长度为y。若能构造,输出YES和这个序列。不能,则输出NO。

解法

可以把n分为若干个长度为y的倒序块,然后判断前面正序的数字是否够x个,如果够则直接输出,否则,把右侧的倒序块一个个转变为正序即可,如果最后一个倒序块被改变,就输出NO。

代码

#include <bits/stdc++.h>
#define IO ios::sync_with_stdio(0), cin.tie(0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;
const int inf = ~0u >> 1;
typedef pair<int, int> P;
#define REP(i, a, n) for (int i = a; i < (n); ++i)
#define PER(i, a, n) for (int i = (n)-1; i >= a; --i)
const ll mod = 1e9 + 7;
int ans[maxn];
int main() {
    IO;
    int t;
    cin >> t;
    while (t--) {
        int n, x, y;
        cin >> n >> x >> y;
        if (x == 1 || y == 1) {
            if (x + y != n + 1) {
                cout << "NO" << endl;
                continue;
            } else {
                 cout<<"YES"<<endl;
                if (x == n) {
                    REP(i, 1, n + 1) {
                        if (i != 1) cout << ' ';
                        cout << i;
                    }
                } else {
                    PER(i, 1, n + 1) {
                        if (i != n) cout << ' ';
                        cout << i;
                    }
                }
                cout << endl;
                continue;
            }
        } else {
            if (x + y - 1 > n) {
                cout << "NO" << endl;
                continue;
            }
            cout<<"YES"<<endl;
            int sum = 0;
            int num = n;
            PER(i, 1, x + 1) {
                int t = min(n - sum - (i - 1), y);
                sum += t;
                int tt = 1;
                //cout << "t = " << t << endl;
                PER(j, num - t + 1, num + 1) { 
                    ans[n - sum + tt] = j; 
                    //cout << "ans[" << n - sum + tt << "] = " << j << endl;
                    tt++;
                }
                

                num -= t;
            }
            REP(i, 1, n + 1) {
                if (i != 1) cout << ' ';
                cout << ans[i];
            }
            cout << endl;
        }
    }
    return 0;

}

J Jogging

题意

在一个二维平面上有一个初始点(x,y),规定“好点”是满足gcd(x,y)>1,现在从点(x,y)开始,
每一次都能等概率的选择:
1.去周围八个方向中的“好点”
2.停留在原地不动
问当走无穷多次步数之后,能够从点(x,y)出发之后回到点(x,y)的概率是多少。

解法

计算答案的时候,需要用到一个结论 (s的度数+1)/(整张图的总度数+n),在本题中如果当前点和
y=x这条直线不连通,那么联通块大小也不会很大,否则由于y=x无限长,无穷步之后回到s的概率为0

代码

#include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i ++)
#define rep1(i, n) for(int i = 1; i <= (int)(n); i ++)
#define MP make_pair

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MOD = 998244353;

map<pair<LL, LL>, int> vis;
int cnt;

LL gcd(LL u, LL v)
{
    return v == 0 ? u : gcd(v, u % v);
}

bool dfs(LL x, LL y)
{
    if(x == y) return true;
    if(vis.find(MP(x, y)) != vis.end()) return false;
    vis[MP(x, y)] = 1;
    cnt ++;
    if(gcd(x, y + 1) != 1) {
        if(dfs(x, y + 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x + 1, y) != 1) {
        if(dfs(x + 1, y)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x, y - 1) != 1) {
        if(dfs(x, y - 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x - 1, y) != 1) {
        if(dfs(x - 1, y)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x + 1, y + 1) != 1) {
        if(dfs(x + 1, y + 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x + 1, y - 1) != 1) {
        if(dfs(x + 1, y - 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x - 1, y - 1) != 1) {
        if(dfs(x - 1, y - 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    if(gcd(x - 1, y + 1) != 1) {
        if(dfs(x - 1, y + 1)) return true;
        vis[MP(x, y)] ++;
        cnt ++;
    }
    return false;
}

void solve()
{
    LL x, y;
    scanf("%lld%lld", &x, &y);
    vis.clear();
    cnt = 0;
    if(dfs(x, y)) printf("0/1\n");
    else {
        int c0 = vis[MP(x, y)], c1 = cnt;
        int g = gcd(c0, c1);
        printf("%d/%d\n", c0 / g, c1 / g);
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --) solve();
    return 0;
}

K

题意

解法

代码

//将内容替换成代码
posted @ 2020-09-01 23:03  cugbacm03  阅读(163)  评论(0)    收藏  举报