zoukankan      html  css  js  c++  java
  • 【11.1校内测试】【快速幂DP】【带权并查集】【模拟】

    Solution

    $jzy$大佬用了给的原根的信息,加上矩阵快速幂150行QAQ

    然而$yuli$大佬的做法不仅好懂,代码只有50行!

    快速幂的思想,把m看成要组成的区间总长度,每次将两段组合得到新的长度。

    定义$g[i]$表示当前x为$i$时的方案数,用来最后计算期望,在快速幂中相当于ans,定义$f[i]$代表a,是初始要用来组合的长度为1的方案,再用一个辅助数组转移即可。

    Code

    #include<bits/stdc++.h>
    #define MOD 1000000007
    #define LL long long
    using namespace std;
    
    LL mpow(LL a, LL b) {
        LL ans = 1;
        for(; b; b >>= 1, a = a * a % MOD)
            if(b & 1)    ans = ans * a % MOD;
        return ans;
    }
    
    int n, m, mod, a;
    LL f[1005], fz[1005], g[1005];
    int main() {
        freopen("rand.in", "r", stdin);
        freopen("rand.out", "w", stdout);
        scanf("%d%d%d", &n, &m, &mod);
        for(int i = 1; i <= n; i ++)    scanf("%d", &a), f[a] ++;
        g[1] = 1; int M = m;
        while(m) {
            if(m % 2) {
                for(int i = 1; i < mod; i ++)    fz[i] = 0;
                for(int i = 1; i < mod; i ++)
                    for(int j = 1; j < mod; j ++)
                        fz[i * j % mod] = (fz[i * j % mod] + 1ll * g[i] * f[j]) % MOD;
                for(int i = 1; i < mod; i ++)    g[i] = fz[i];
            }
            for(int i = 1; i < mod; i ++)    fz[i] = 0;
            for(int i = 1; i < mod; i ++)
                for(int j = 1; j < mod; j ++)
                    fz[i * j % mod] = (fz[i * j % mod] + 1ll * f[i] * f[j]) % MOD;
            for(int i = 1; i < mod; i ++)    f[i] = fz[i];
            m >>= 1;
        }
        LL ans = 0;
        for(int i = 1; i <= mod; i ++)    ans = (ans + 1ll * g[i] * i) % MOD;
        ans = ans * mpow(mpow(n, M), MOD - 2) % MOD;
        printf("%lld", ans);
        return 0;
    }

    Solution

    完全没想到是带权并查集!!

    网上大佬讲解的很好!写的时候细节也比较多,对带权并查集理解深了一层了QAQ想不通的一点就是排序如果按二维排就会错一个点??

    Code

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    inline LL read() {
        LL x = 0;    int t = 0;    char ch = getchar();
        while(!isdigit(ch))    t |= (ch == '-'), ch = getchar();
        while(isdigit(ch))    x = x * 10 + ch - '0', ch = getchar();
        return x * (t ? -1 : 1);
    }
    
    struct Node {
        int x, y; LL w;
    } a[100005];
    bool cmp1(Node a, Node b) { return a.x < b.x; }
    bool cmp2(Node a, Node b) { return a.y < b.y; }
    
    LL fx[100005], fy[100005], wx[100005], wy[100005];
    int findx(int x) {
        if(fx[x] == x)    return fx[x];
        int hx = findx(fx[x]);
        wx[x] += wx[fx[x]];
        return fx[x] = hx;
    }
    
    bool checkx(int x, int y, LL w) {
        int hx = findx(x), hy = findx(y);
        if(hx == hy)    return wx[x] == wx[y] + w;
        fx[hx] = hy;    wx[hx] = wx[y] + w - wx[x];
        return 1;
    }
    
    int findy(int x) {
        if(fy[x] == x)    return fy[x];
        int hy = findy(fy[x]);
        wy[x] += wy[fy[x]];
        return fy[x] = hy;
    }
    
    bool checky(int x, int y, LL w) {
        int hx = findy(x), hy = findy(y);
        if(hx == hy)    return wy[x] == wy[y] + w;
        fy[hx] = hy;    wy[hx] = wy[y] + w - wy[x];
        return 1;
    }
    
    int R, C, n;
    LL Min[100005], Max[100005];
    bool work() {
        R = read(), C = read();
        n = read();
        memset(Min, 127, sizeof(Min));
        memset(Max, 127, sizeof(Max));
        int p = 1;
        for(int i = 1; i <= n; i ++) {
            a[i].x = read(), a[i].y = read(), a[i].w = read();
            if(a[i].w < 0 || (R * C <= 12 && a[i].w >= 3 && R != 1))    p = 0;
        }
        if(!p)    return 0;
        for(int i = 1; i <= R; i ++)    fx[i] = i, wx[i] = 0;
        for(int i = 1; i <= C; i ++)    fy[i] = i, wy[i] = 0;
        sort(a + 1, a + 1 + n, cmp1);
        for(int i = 1; i < n; i ++) {
            if(a[i].x == a[i + 1].x && !checky(a[i].y, a[i + 1].y, a[i + 1].w - a[i].w))
                return 0;
        }
        sort(a + 1, a + 1 + n, cmp2);
        for(int i = 1; i < n; i ++) {
            if(a[i].y == a[i + 1].y && !checkx(a[i].x, a[i + 1].x, a[i + 1].w - a[i].w))
                return 0;
        }
        for(int i = 1; i <= n; i ++) {
            int x = findx(a[i].x);
            Min[x] = min(Min[x], a[i].w + wx[a[i].x]);
        }
        for(int i = 1; i <= R; i ++) {
            int x = findx(i);
            Max[x] = min(Max[x], -wx[i]);
        }
        for(int i = 1; i <= R; i ++) {
            if(Min[i] + Max[i] < 0 && fx[i] == i)    return 0;
        }
        return 1;
    }
    
    int main() {
        freopen("then.in", "r", stdin);
        freopen("then.out", "w", stdout);
        int T;
        scanf("%d", &T);
        while(T --) {
            if(work())    puts("Yes");
            else        puts("No");
        }
        return 0;
    }

    Solution

    乍一看怎么那么像聪聪与可可??然而这实际上是面具下隐藏着的小模拟!!!QAQ

    仔细读读题发现自己的移动根本是没有用的,因为这一步除了使距离拉近一步外什么都没有做,不如给自己回蓝或者尽量去打香港记者,因为此时的距离的贡献一定比以后优。

    然后就是能打就打,不能打就回蓝。

    香港记者走的永远是受伤害最小的地方,因此要比较三个方位,然而就是这里让100分打水漂了QAQ

    因为在最后他也可以只走一步,不一定一定要走两步,所以下面的写法就很精髓了QAQ

    for(int i = 1; i <= 2; i++) {
    	if(tx == 0 && ty == 0)	break;
    	if(tx <= ty)	ty--;
    	else tx--;	
    }

    Code

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    inline int read() {
        int x = 0;    int t = 0;    char ch = getchar();
        while(!isdigit(ch))    t |= (ch == '-'), ch = getchar();
        while(isdigit(ch))    x = x * 10 + ch - '0', ch = getchar();
        return x * (t ? -1 : 1);
    }
    
    int a, b;
    int a1, a2, b1, b2, c, d;
    
    inline LL Min(LL a, LL b) {
        return a < b ? a : b;
    }
    
    void work() {
        a1 = read(), b1 = read(), a2 = read(), b2 = read(), c = read(), d = read();
        int tx = abs(a1 - a2), ty = abs(b1 - b2);
        int flag = 1;
        while(1) {
            if(d <= 0)    break;
            if(tx == 0 && ty == 0) { flag = 0;    break; }
            if(c < a)    c += b;
            else    c -= a, d -= tx * tx + ty * ty;
            if(d <= 0)    break;
            for(int i = 1; i <= 2; i++) {
                if(tx == 0 && ty == 0)    break;
                if(tx <= ty)    ty--;
                else tx--;    
            }
        }
        if(flag)    printf("NAIVE
    ");
        else        printf("SIMPLE
    ");
    }
    
    int main() {
        freopen("do.in", "r", stdin);
        freopen("do.out", "w", stdout);
        int T;
        T = read();
        a = read(), b = read();
        while(T --) {
            work();
        }
        return 0;
    }
  • 相关阅读:
    团队冲刺第四天
    团队冲刺第三天
    团队冲刺第二天
    团队冲刺第一天
    全球疫情地图显示
    团队博客——keep running视频+PPT介绍
    周总结7
    人月神话阅读笔记03
    Java枚举类型的使用,数值的二进制表示
    四则运算器
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9891291.html
Copyright © 2011-2022 走看看