zoukankan      html  css  js  c++  java
  • Codeforces 987 K预处理BFS 3n,7n+1随机结论题/不动点逆序对 X&Y=0连边DFS求连通块数目

    A

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = 55 + 5;
    int n, K;
    ll sum[N][N];
    ll a[N];
    bool dp[N][N];
    map<string, int> mp2;
    map<int, string> mp;
    int visit[10];
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            mp2["purple"] = 1;
            mp2["green"] = 2;
            mp2["blue"] = 3;
            mp2["orange"] = 4;
            mp2["red"] = 5;
            mp2["yellow"] = 6;
            mp[1] = "Power";
            mp[2] = "Time";
            mp[3] = "Space";
            mp[4] = "Soul";
            mp[5] = "Reality";
            mp[6] = "Mind";
            int n;
            cin >> n;
            for (int i = 1; i <= n; i++)
            {
                    string now;
                    cin >> now;
                    visit[mp2[now]]++;
            }
            cout << 6 - n << endl;
            for (int i = 1; i <= 6; i++)
            {
                    if (!visit[i])
                    {
                            cout << mp[i] << endl;
                    }
            }
            return 0;
    }
    View Code

    B

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = 55 + 5;
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            ll x, y;
            cin >> x >> y;
            if (x == y || x == 2 && y == 4 || x == 4 && y == 2)
            {
                    cout << "=" << endl;
                    return 0;
            }
            if (x == 1 || y == 1)
            {
                    if (x == 1)
                    {
                            cout << "<" << endl;
                    }
                    else
                    {
                            cout << ">" << endl;
                    }
                    return 0;
            }
            if (max(x, y) <= 10)
            {
                    ll ansx = 1;
                    for (int i = 1; i <= y; i++)
                    {
                            ansx *= x;
                    }
                    ll ansy = 1;
                    for (int i = 1; i <= x; i++)
                    {
                            ansy *= y;
                    }
                    if (ansx > ansy)
                    {
                            cout << ">" << endl;
                    }
                    else
                    {
                            cout << "<" << endl;
                    }
                    return 0;
            }
            if (x > y)
            {
                    cout << "<" << endl;
            }
            else
            {
                    cout << ">" << endl;
            }
            return 0;
    }
    View Code

    C

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = 55 + 5;
    int num[3005];
    ll cost[3005];
    ll dp[3005][4];
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            int n;
            cin >> n;
            for (int i = 1; i <= n; i++)
            {
                    cin >> num[i];
            }
            for (int i = 1; i <= 3000; i++)
            {
                    for (int j = 1; j <= 3; j++)
                    {
                            dp[i][j] = LLONG_MAX;
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    cin >> cost[i];
                    dp[i][1] = cost[i];
            }
            for (int i = 2; i <= n; i++)
            {
                    for (int j = i - 1; j >= 1; j--)
                    {
                            for (int k = 2; k <= 3; k++)
                            {
                                    if (dp[j][k - 1] != LLONG_MAX&&num[i]>num[j])
                                    {
                                            dp[i][k] = min(cost[i] + dp[j][k - 1], dp[i][k]);
                                    }
                            }
                    }
            }
            ll anser = LLONG_MAX;
            for (int i = 1; i <= n; i++)
            {
                    anser = min(anser, dp[i][3]);
            }
            if (anser == LLONG_MAX)
            {
                    cout << -1 << endl;
            }
            else
            {
                    cout << anser << endl;
            }
            return 0;
    }
    View Code

    D. Fair

    题意:

    给你N个点M条边的连通图(100000) 和K个特殊地方(100) S个目标地(100)

    每个特殊的地方有某种特产 问你从1到N每个点要拿S个特产的最少的花费

    解:

    给每个特产都建一个超级点 然后BFS 处理出1到N每个点到每种特产的最小距离

    然后贪心取前S个即可 复杂度nklogk

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = 1e5 + 105;
    int p[N];
    vector<int> g[N];
    int ans[N];
    int dist[N];
    int que[N];
    int dp[N][105];
    int getl, getr;
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            int n, m, k, s;
            cin >> n >> m >> k >> s;
            for (int i = 1; i <= n; i++)
            {
                    cin >> p[i];
            }
            int u, v;
            for (int i = 1; i <= m; i++)
            {
                    cin >> u >> v;
                    g[u].pb(v);
                    g[v].pb(u);
            }
            for (int i = 1; i <= k; i++)
            {
                    getl = 1;
                    getr = 0;
                    mem(dist, 0);
                    for (int j = 1; j <= n; j++)
                    {
                            if (p[j] == i)
                            {
                                    dist[j] = 1;
                                    que[++getr] = j;
                            }
                    }
                    while (getl <= getr)
                    {
                            int len = g[que[getl]].size();
                            for (int w = 0; w < len; w++)
                            {
                                    int to = g[que[getl]][w];
                                    if (!dist[to])
                                    {
                                            dist[to] = dist[que[getl]] + 1;
                                            que[++getr] = to;
                                    }
                            }
                            getl++;
                    }
                    for (int j = 1; j <= n; j++)
                    {
                            dp[j][i] = dist[j] - 1;
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    sort(dp[i] + 1, dp[i] + 1 + k);
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= s; j++)
                    {
                            ans[i] += dp[i][j];
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    cout << ans[i] << " ";
            }
            cout << endl;
            return 0;
    }
    View Code

    E. Petr and Permutations

    题意:

    给你1到N的一种排列 A会选3n次每次随机一对位置交换 B会选7n+1次

    问你给你的数列是A得到的可能性大还是B的可能性大

    ①:

    可以猜到结论 观察可以得知3n和7n+1的奇偶性永远是不同的

    所以我们计算原数列所需要的最小交换次数 当这个次数与A奇偶性相同就是A 反之则是B

    (因为要与原数列相同的话在最小交换次数基础上要加偶数次)

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = 1e6 + 105;
    int par[N], hs[N];
    int sz[N];
    int num[N];
    int cnt;
    void init(int n)
    {
            for (int i = 0; i <= n; i++)
            {
                    par[i] = i, hs[i] = i, sz[i] = 1;
            }
    }
    int find(int x)
    {
            return par[x] == x ? x : par[x] = find(par[x]);
    }
    void unite(int x, int y)
    {
            x = find(x);
            y = find(y);
            if (x != y)
            {
                    par[x] = y, sz[y] += sz[x];
            }
    }
    int visit[N];
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
            int n;
            cin >> n;
            init(n);
            for (int i = 1; i <= n; i++)
            {
                    cin >> num[i];
            }
            for (int i = 1; i <= n; i++)
            {
                    if (num[i] != i)
                    {
                            unite(i, num[i]);
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    par[i] = find(i);
            }
            ll anser = 0;
            for (int i = 1; i <= n; i++)
            {
                    if (!visit[par[i]])
                    {
                            anser += sz[par[i]] - 1;
                            visit[par[i]] = 1;
                    }
            }
            //cout << anser << endl;
            if (anser % 2 == 3 * n % 2)
            {
                    cout << "Petr" << endl;
            }
            else
            {
                    cout << "Um_nik" << endl;
            }
            return 0;
    }
    View Code

    ②:

    也可以用不动点+逆序对分情况处理

    当n不小于20000时 考察不动点的数量  n小于20000时取逆序对的数量判断奇偶性

    int main()
    {
        int i,j,a1,a2;
        _(n);
        fo(i,n)
            _(a[i]);
        fo(i,n)
            an+=(a[i]==i);
        if(n>=20000)
            puts(an>=20?"Petr":"Um_nik");
        else
        {
            fo(i,n)            
            fo1(j,i+1,n)
                if(a[j]<a[i])
                    ans++;
            puts((ans+n)%2?"Um_nik":"Petr");
        }
    }
    View Code

    F. AND Graph

    题意:

    给你0 - 2n-1范围中的m个数 (n<=22)

    如果两个数字Ai A两个&的值为0 则这两个点之间有一条边 问你最后的连通块有几个

    解:

    暴力题.. 假设有X,Y两个数 X的二进制恰好是Y的基础上多出一位1  比如 101 与 001 我们称X为Y的祖先 Y是X的子孙

    这样能与祖先X相连的点 肯定能和Y相连 这样X,Y其实就通过对立数间接相连

    所以我们每次DFS一个数的时候 把X全部子孙找出来 也把所有对立数(包括子孙的)找出来 他们肯定就是一个连通块

    因为N最大是22 所以我们可以直接暴力循环枚举 开两个bool 数组 num[i]为true表示i是被选中的数 而vis[i]为true表示i被DFS过了

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7;
    const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int N = (1 << 22) + 5;
    int n, m, now;
    int anser;
    bool num[N], vis[N];
    void dfs(int x)
    {
            if (vis[x])  //如果之前已经DFS到过
            {
                    return ;
            }
            vis[x] = true;
            for (int i = 0; i < n; i++)
                    if (x & (1 << i))  //DFS每个二进制比X少一位1的数保证main循环中不会被循环到
                    {
                            dfs(x ^ (1 << i));
                    }
            if (num[x])  //如果X是存在的 找所有X对立面的数
            {
                    dfs((1 << n) - 1 - x);
            }
    }
    int main()
    {
            cin >> n >> m;
            for (int i = 1; i <= m; i++)
            {
                    scanf("%d", &now);
                    num[now] = true;
            }
            for (int i = (1 << n) - 1; i >= 0; i--)
                    if (!vis[i] && num[i])  //如果有存在的数且没有被DFS到
                    {
                            anser++;  //连通块答案数+1
                            dfs((1 << n) - 1 - i); //DFS全部与i连通的数
                    }
            cout << anser << endl;
            return 0;
    }
    View Code
  • 相关阅读:
    条件转移指令小结
    《那些年啊,那些事——一个程序员的奋斗史》——50
    《那些年啊,那些事——一个程序员的奋斗史》——50
    《那些年啊,那些事——一个程序员的奋斗史》——51
    《那些年啊,那些事——一个程序员的奋斗史》——51
    《那些年啊,那些事——一个程序员的奋斗史》——52
    《那些年啊,那些事——一个程序员的奋斗史》——49
    《那些年啊,那些事——一个程序员的奋斗史》——51
    《那些年啊,那些事——一个程序员的奋斗史》——52
    《那些年啊,那些事——一个程序员的奋斗史》——50
  • 原文地址:https://www.cnblogs.com/Aragaki/p/9110472.html
Copyright © 2011-2022 走看看