校赛部分题解

校赛部分题解

A,第一集,这是怎么肥死嘛

统计字母签到题

#include <bits/stdc++.h>

using namespace std;
const int MAXN = 1e5 + 10;

int t, n;

char str[MAXN];

int cnt[10];

int main()
{
    map<char, int>mp;
    
    //hello world

    mp['h'] = 1; // 1
    mp['e'] = 2; // 1
    mp['l'] = 3; // 3
    mp['o'] = 4; // 2
    mp['w'] = 5; // 1
    mp['r'] = 6; // 1
    mp['d'] = 7; // 1

    scanf("%d", &t);
    while(t--) {
        
        scanf("%s", str);
        n = strlen(str);

        memset(cnt, 0, sizeof(cnt));

        for(int i = 0; i < n; i++ ) {
            if(mp.count(str[i])) {
                cnt[ mp[str[i]] ]++;
            }
        }

        cnt[ mp['l'] ] /= 3;
        cnt[ mp['o'] ] /= 2;

        int ans = 0x3f3f3f3f;
        for(int i = 1; i <= 7; i++ ) {
            ans = min(ans, cnt[i]);
        }

        printf("%d\n", ans);

    }


    return 0;
}

/**
3
helloworld
helloworldooooooooooo
helloworldhelloworldasjdkl
*/

I, 第五集,不要007,要睡觉

类似题: HDU 5950,我随手改了递推式

这么裸的矩阵快速幂 F[n] = 2 * f[n - 1] + 3 * f[n - 2] + 3 * n^5 , 除了那个n^5。

第一项,第二项直接输出答案

当 n >= 3 时, 我们假设

\[ A_n=\left[ \begin{matrix} F[n] & F[n-1] & n^5 & n^4 & n^3 & n^2 & n^1 & n^0\\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ \end{matrix} \right] \]

\[ A_{n+1}=\left[ \begin{matrix} F[n+1] & F[n] & (n+1)^5 & (n+1)^4 & (n+1)^3 & (n+1)^2 & n+1 & 1\\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ \end{matrix} \right] \]

假设一个矩阵B, 我们需要算一个B使得

\[ A_{n+1} = A_n * B \]

按照矩阵乘法规则易得

\[ B=\left[ \begin{matrix} 2 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 3 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 3 & 0 & 1 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 5 & 1 & 0 & 0 &0 &0 \\ 0 & 0 & 10 & 4 & 1 & 0 &0 &0 \\ 0 & 0 & 10 & 6 & 3 & 1 &0 &0 \\ 0 & 0 & 5 & 4 & 3 & 2 &1 &0 \\ 0 & 0 & 1 & 1 & 1 & 1 &1 &1 \\ \end{matrix} \right] \]

所以我们假设

\[ A = \left[ \begin{matrix} b & a & 3^5 & 3^4 & 3^3 & 3^2 & 3^1 & 3^0\\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ \end{matrix} \right] \]

\[ B = \left[ \begin{matrix} 2 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 3 & 0 & 0 & 0 & 0 & 0 &0 &0 \\ 3 & 0 & 1 & 0 & 0 & 0 &0 &0 \\ 0 & 0 & 5 & 1 & 0 & 0 &0 &0 \\ 0 & 0 & 10 & 4 & 1 & 0 &0 &0 \\ 0 & 0 & 10 & 6 & 3 & 1 &0 &0 \\ 0 & 0 & 5 & 4 & 3 & 2 &1 &0 \\ 0 & 0 & 1 & 1 & 1 & 1 &1 &1 \\ \end{matrix} \right] \]

令矩阵 C = A * B ^ (n - 2), 答案为C[0][0]

标称

#include <bits/stdc++.h>

using namespace std;
const int MAXN = 110;
typedef long long LL;
const LL MOD = 2147493647;
#define mod(x) ((x)%MOD)

int n = 8;

struct Mat {
    LL m[MAXN][MAXN];
    void init() {
        memset(m, 0, sizeof(m));
    }
    void set() {
        init();
        for(int i = 0; i < MAXN; i++ ) {
            m[i][i] = 1;
        }
    }
    void disp() {
        for(int i = 0; i < n; i++ ) {
            for(int j = 0; j < n; j++ ) {
                printf("%-10d", m[i][j]);
            }
            puts("");
        }
    }
} unit;

Mat operator * (const Mat &a, const Mat &b) {
    Mat ret;
    ret.init();
    LL x = 0;
    for(int i = 0; i < n; i++ ) {
        for(int j = 0; j < n; j++ ) {
            x = 0;
            for(int k = 0; k < n; k++ ) {
                x += mod((a.m[i][k] % MOD) * (b.m[k][j] % MOD));
                x = mod(x);
            }
            ret.m[i][j] = mod(x);
        }
    }
    return ret;
}

Mat pow_mod(Mat a, LL n) {
    Mat ret = unit;
    while(n) {
        if(n & 1) {
            ret = ret * a;
        }
        a = a * a;
        n >>= 1;
    }
    return ret;
}

LL pow_mod(LL a, LL b) {
    LL res = 1;
    while(b) {
        if(b & 1) {
            res = (res * a) % MOD;
        } 
        b >>= 1;
        a = (a * a) % MOD;
    }
    return res;
}

int T;

LL N, a, b;

int map_b[8][8] = 
{
    2, 1, 0, 0, 0, 0, 0, 0,
    3, 0, 0, 0, 0, 0, 0, 0,
    3, 0, 1, 0, 0, 0, 0, 0,
    0, 0, 5, 1, 0, 0, 0, 0,
    0, 0,10, 4, 1, 0, 0, 0,
    0, 0,10, 6, 3, 1, 0, 0,
    0, 0, 5, 4, 3, 2, 1, 0,
    0, 0, 1, 1, 1, 1, 1, 1
};

LL solve_check()
{
    if(N == 1) {
        //printf("%lld\n", a);
        return a;
    }
    if(N == 2) {
        //printf("%lld\n", b);
        return b;
    }
    LL c = 0;
    vector<LL>v;
    v.push_back(0);
    v.push_back(a);
    v.push_back(b);
    for(int i = 3; i <= N; i++ ) {
        LL va = v[i - 1] * 2;
        va %= MOD;
        va += v[i - 2] * 3;
        va %= MOD;
        va += 3 * pow_mod(i, 5);
        va %= MOD;
        v.push_back(va);       
    }
    return v[N];
}

LL solve_std()
{
    if(N == 1) {
        //printf("%lld\n", a);
        return a;
    }
    if(N == 2) {
        //printf("%lld\n", b);
        return b;
    }
    Mat A, B;
    A.init();
    B.init();

    A.m[0][0] = b;
    A.m[0][1] = a;
    A.m[0][2] = 3 * 3 * 3 * 3 * 3;
    A.m[0][3] = 3 * 3 * 3 * 3;
    A.m[0][4] = 3 * 3 * 3;
    A.m[0][5] = 3 * 3;
    A.m[0][6] = 3;
    A.m[0][7] = 1;

    for(int i = 0; i < 8; i++ ) {
        for(int j = 0; j < 8; j++ ) {
            B.m[i][j] = map_b[i][j];
        }
    }
    Mat res = A * pow_mod(B, N - 2);
    return res.m[0][0] % MOD;
}

void judge_std()
{
    freopen("data.in", "w", stdout);

    srand(static_cast<unsigned int>(time(0)));
    
    LL MAX = (1LL << 31);

    int cas = 1000;

    printf("%d\n", cas);

    for(int i = 1; i <= cas; i++ ) {
        N = rand() % MAX + 1;
        a = rand() % MAX + 1;
        b = rand() % MAX + 1;
        
        printf("%lld %lld %lld\n", N, a, b);

        continue;

        LL ans1 = solve_std();
        LL ans2 = solve_check();
        if(ans1 != ans2) {
            puts(ans1 == ans2 ? "Yes" : "No");
            printf("cas = %d %lld %lld %lld\n", i, N, a, b);
            printf("%lld %lld\n", ans1, ans2);
            puts("error");
            return ;
        }
    }
    //puts("Accept");
}

int main()
{

  //  freopen("data.in", "r", stdin);
  //  freopen("data.out", "w", stdout);

    unit.set();

    //judge_std();


    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld %lld", &N, &a, &b);
        printf("%lld\n", solve_std());
    }
    return 0;
}

L, 第八集,我要是不呢?

类似题: BZOJ 2400 SPOJ839

前置技能网络流最小割

异或运算中二进制位之间没有影响。我们可以把每一位单独处理。

那么对于某一个二进制位。变成了取0和取1,不同就会对答案有贡献,对于边权的贡献最少?

下面我们只针对二进制某一位。

那么我们可以看成两种决策,一种把点归成0, 另一种归为1,那么点的两种决策就会造成贡献,我们要让它最小。就变成二选一的最小割模型了。

我们对原图的边,建立双向边,权为1。对于某一位已知01的点,分别划分两个集合,一个连源点,一个汇点,权无穷大。那么我们求该图的最小割。就会在割掉某些边,使得点属于某一个集合,0集合或者1集合。我们要的边权最小也符合最小割的定义。最后我们跑最大流即可。然后在吧每一位的答案整合。

#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 555;
const int MAX_M = 3050 * 2;

int n, m, k;

struct Edge {
    int u, v;
} edge[MAX_M];

int p[MAX_N], v[MAX_N];

int vis[MAX_N];

struct Dinic {

    static const int MAXN = 500 + 7;
    static const int MAXM = MAXN * MAXN;
    static const int INF = 0x3f3f3f3f;

    int n, m, s, t;

    int first[MAXN], cur[MAXN], dist[MAXN], sign;

    struct Node {
        int to, flow, next;
    } edge[MAXM * 4];

    inline void init(int start, int vertex, int ss, int tt) {
        n = vertex, s = ss, t = tt;
        for(int i = start; i <= n; i++ ) {
            first[i] = -1;
        }
        sign = 0;
    }

    inline void addEdge(int u, int v, int flow) {
        edge[sign].to = v, edge[sign].flow = flow, edge[sign].next = first[u];
        first[u] = sign++;
    }

    inline void add_edge(int u, int v, int flow) {
        addEdge(u, v, flow);
        addEdge(v, u, 0);
    }

    inline int dinic() {
        int max_flow = 0;
        while(bfs(s, t)) {
            for(int i = 0; i <= n; i++ ) {
                cur[i] = first[i];
            }
            max_flow += dfs(s, INF);
        }
        return max_flow;
    }

    bool bfs(int s, int t) {
        memset(dist, -1, sizeof(dist));
        queue<int>que;
        que.push(s), dist[s] = 0;
        while(!que.empty()) {
            int now = que.front();
            que.pop();
            if(now == t) {
                return 1;
            }
            for(int i = first[now]; ~i; i = edge[i].next) {
                int to = edge[i].to, flow = edge[i].flow;
                if(dist[to] == -1 && flow > 0) {
                    dist[to] = dist[now] + 1;
                    que.push(to);
                }
            }
        }
        return 0;
    }

    int dfs(int now, int max_flow) {
        if(now == t) {
            return max_flow;
        }
        int ans = 0, next_flow = 0;
        for(int &i = cur[now]; ~i; i = edge[i].next) {
            int to = edge[i].to, flow = edge[i].flow;
            if(dist[to] == dist[now] + 1 && flow > 0) {
                next_flow = dfs(to, min(max_flow - ans, flow));
                ans += next_flow;
                edge[i].flow -= next_flow;
                edge[i ^ 1].flow += next_flow;
                if(ans == max_flow) {
                    return max_flow;
                }
            }
        }
        if(ans == 0) {
            return dist[now] = 0;
        }
        return ans;
    }

    void find_set_s(int x) {
        vis[x] = 1;
        for(int i = first[x]; ~i; i = edge[i].next) {
            int to = edge[i].to, flow = edge[i].flow;
            if(!vis[to] && flow) {
                find_set_s(to);
            }
        }
    }
} cwl;

int ans[MAX_N];

int main() {

    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= m; i++ ) {
            scanf("%d %d", &edge[i].u, &edge[i].v);
        }
        scanf("%d", &k);
        for(int i = 1; i <= k; i++ ) {
            scanf("%d %d", &p[i], &v[i]);
        }
        memset(ans, 0, sizeof(ans));
        for(int bit = 0; bit < 31; bit++ ) {
            cwl.init(0, n + 1, 0, n + 1);
            for(int i = 1; i <= m; i++ ) {
                int u = edge[i].u, v = edge[i].v;
                cwl.add_edge(u, v, 1);
                cwl.add_edge(v, u, 1);
            }
            for(int i = 1; i <= k; i++ ) {
                if((v[i] >> bit) & 1) {
                    cwl.add_edge(0, p[i], cwl.INF);
                } else {
                    cwl.add_edge(p[i], n + 1, cwl.INF);
                }
            }
            cwl.dinic();
            memset(vis, 0, sizeof(vis));
            cwl.find_set_s(0);
            for(int i = 1; i <= n; i++ ) {
                if(vis[i]) {
                    ans[i] += (1 << bit);
                }
            }
        }
        //for(int i = 1; i <= n; i++ ) {
        //    printf("data = %d\n", ans[i]);
        //}
        long long res = 0;
        for(int i = 1; i <= m; i++ ) {
            res += ans[ edge[i].u ] ^ ans[ edge[i].v ];
        }
        printf("%lld\n", res);
    }

    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务