• 【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】


    Solution

    注意取模!!!

    Code

    #include<bits/stdc++.h>
    #define mod 1000000007
    #define LL long long
    using namespace std;
    
    int n, a, b;
    
    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;
    }
    
    LL fac[200005], inv[200005], l[100005], t[100005];
    void init() {
        fac[0] = 1;
        inv[0] = 1;
        for(int i = 1; i <= 200000; i ++) {
            fac[i] = fac[i - 1] * i % mod;
            inv[i] = mpow(fac[i], mod - 2);
        }
    }
    
    LL C(int p, int q) {
        return fac[p] * inv[q] % mod * inv[p - q] % mod;
    }
    
    int main() {
        freopen("matrix.in", "r", stdin);
        freopen("matrix.out", "w", stdout);
        scanf("%d%d%d", &n, &b, &a);
        for(int i = 1; i <= n; i ++)    scanf("%lld", &l[i]);
        for(int i = 1; i <= n; i ++)    scanf("%lld", &t[i]);
        LL ans = 0;
        init();
        for(int i = 2; i <= n; i ++) {
            ans = (ans + b * l[i] % mod * C(n - 2 + n - i, n - 2) % mod * mpow(a, n - i) % mod * mpow(b, n - 2) % mod) % mod;
            ans = (ans + a * t[i] % mod * C(n - 2 + n - i, n - 2) % mod * mpow(b, n - i) % mod * mpow(a, n - 2) % mod) % mod;
        }
        printf("%lld", ans);
        return 0;
    }

    Solution

    二分+DP,二分需要多少组p+q,记忆化搜索判断是否可以达到条件。

    定义$dp[dep][j][k]$表示当前取到第$dep$个数,还需要j个p,k个q来使满足条件。(p>q)

    每次先尽量放p,剩下中再尽量放q,放q时就有限制,不能取超过$mid-i$,i表示当前取的p的数量。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    
    int n, a[55], p, q;
    int sum[55], vis[55][1005][1005], tim, all;
    bool dfs(int dep, int nump, int numq) {
        if(nump == 0 && numq == 0)    return 1;
        if(dep == n + 1 || sum[dep] < nump * p + numq * q)    return 0;
        if(vis[dep][nump][numq] == tim)    return 0;
        for(int i = 0; i <= min(nump, a[dep] / p); i ++)
            if(dfs(dep + 1, nump - i, max(numq - min((a[dep] - p * i) / q, all - i), 0)))    return 1;
        vis[dep][nump][numq] = tim;
        return 0;
    }
    
    bool check(int mid) {
        tim ++;
        all = mid;
        return dfs(1, mid, mid);
    }
    
    int erfen() {
        int l = 0, r = sum[1] / (p + q), ans;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(check(mid))    ans = mid, l = mid + 1;
            else    r = mid - 1;
        }
        return ans;
    }
    
    int main() {
        freopen("pq.in", "r", stdin);
        freopen("pq.out", "w", stdout);
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)    scanf("%d", &a[i]);
        for(int i = n; i >= 1; i --)    sum[i] = sum[i + 1] + a[i];
        scanf("%d%d", &p, &q);
        if(p < q)    swap(p, q);
        int ans = erfen();
        printf("%d", ans * (p + q));
        return 0;
    }

    Solution

    考试最后半小时开始写QAQ结果发现是做过的题啊??

    可是最后Spfa写错了!!!我爆哭!!!!

    将与1相连的所有点取出来,二进制分类,分成起点和终点,跑多起点多终点的Spfa,处理出两两起点终点间最短路,更新答案即可QAQ

    Spfa要判更新的点不能是1!!

    Code

    #include<bits/stdc++.h>
    using namespace std;
    
    int n, m;
    
    struct Node {
        int v, nex, w;
    } Edge[200005];
    
    int h[30005], stot = 1;
    void add(int u, int v, int w) {
        Edge[++stot] = (Node) {v, h[u], w};
        h[u] = stot;
    }
    
    int dis[30005];
    int vis[30005], nums, numt, w[30005], t[30005], S[30005], T[30005];
    void Spfa1() {
        queue < int > q;
        memset(vis, 0, sizeof(vis));
        memset(dis, 0x3f3f3f3f, sizeof(dis));
        for(int i = 1; i <= nums; i ++)    q.push(S[i]), vis[S[i]] = 1, dis[S[i]] = min(dis[S[i]], w[S[i]]);
        while(!q.empty()) {
            int u = q.front();    q.pop();    vis[u] = 0;
            for(int i = h[u]; i; i = Edge[i].nex) {
                int v = Edge[i].v;
                if(dis[v] > dis[u] + Edge[i].w && v != 1) {
                    dis[v] = dis[u] + Edge[i].w;
                    if(!vis[v]) {
                        vis[v] = 1;    q.push(v);
                    }
                }
            }
        }
    }
    
    void Spfa2() {
        queue < int > q;
        memset(vis, 0, sizeof(vis));
        memset(dis, 0x3f3f3f3f, sizeof(dis));
        for(int i = 1; i <= numt; i ++)    q.push(T[i]), vis[T[i]] = 1, dis[T[i]] = min(dis[T[i]], w[T[i]]);
        while(!q.empty()) {
            int u = q.front();    q.pop();    vis[u] = 0;
            for(int i = h[u]; i; i = Edge[i].nex) {
                int v = Edge[i].v;
                if(dis[v] > dis[u] + Edge[i].w && v != 1) {
                    dis[v] = dis[u] + Edge[i].w;
                    if(!vis[v]) {
                        vis[v] = 1;    q.push(v);
                    }
                }
            }
        }
    }
    
    int tov[30006], tot;
    int main() {
        freopen("graph.in", "r", stdin);
        freopen("graph.out", "w", stdout);
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i ++) {
            int u, v, a, b;
            scanf("%d%d%d%d", &u, &v, &a, &b);
            add(u, v, a);    add(v, u, b);
        }
        int ans = 0x3f3f3f3f;
        memset(w, 0x3f3f3f3f, sizeof(w));
        memset(t, 0x3f3f3f3f, sizeof(t));
        for(int i = h[1]; i; i = Edge[i].nex)
            tov[++tot] = Edge[i].v, w[Edge[i].v] = min(w[Edge[i].v], Edge[i].w), t[Edge[i].v] = min(t[Edge[i].v], Edge[i ^ 1].w);
        sort(tov + 1, tov + 1 + tot);
        int M = tov[tot], tt = 0;
        while(M) {
            int tmp = (M & 1);
            nums = 0, numt = 0;
            for(int i = 1; i <= tot; i ++)
                if(((tov[i] >> tt) & 1) == tmp)    S[++nums] = tov[i];
                else    T[++numt] = tov[i];
            Spfa1(); 
            for(int j = 1; j <= numt; j ++) {
                ans = min(ans, t[T[j]] + dis[T[j]]);
            }
            Spfa2();
            for(int j = 1; j <= nums; j ++) {
                ans = min(ans, t[S[j]] + dis[S[j]]);
            }
            M >>= 1, tt ++;
        }
        printf("%d", ans);
        return 0;
    }
  • 相关阅读:
    jQuery Validate 插件
    本地存储 web storage
    ajax简介及JS写原生ajax
    swiper插件简介及用法
    JavaScript中的string对象及方法
    javascript数组中的方法
    面向对象
    logging模块具体补充
    模块补充
    内置函数总结
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9883516.html
Copyright © 2020-2023  润新知