• 20200328题解


    T1 纯模拟,额外维护每个工件最后的建造时间即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch))
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = (ans << 1) + (ans << 3) + (ch ^ 48), ch = getchar();
        while(isdigit(ch));
        return ans * f;
    }
    
    const int MAXN = 21, MAXT = MAXN*MAXN*MAXN;
    int num[MAXN*MAXN], bel[MAXN][MAXN], cost[MAXN][MAXN], last[MAXN], isWork[MAXN][MAXT], cnt[MAXN];
    
    int main(){
        int m = read(), n = read();
        for(int i=1; i<=m*n; i++)
            num[i] = read();
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                bel[i][j] = read();
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                cost[i][j] = read();
        for(int i=1; i<=n*m; i++){
            cnt[num[i]]++;
            for(int t=last[num[i]]+1, sum=0; t<=MAXT; t++){
                if(!isWork[bel[num[i]][cnt[num[i]]]][t]) sum++;
                else sum = 0;
                if(sum == cost[num[i]][cnt[num[i]]]){
                    for(int j=t-sum+1; j<=t; j++)
                        isWork[bel[num[i]][cnt[num[i]]]][j] = true;
                    last[num[i]] = t;
                    break;
                }
            }
        }
        int ans = 0;
        for(int i=1; i<=n; i++)
            ans = max(ans, last[i]);
        printf("%d", ans);
        return 0;
    }
    View Code

    T2 答案可以在$O(n^2)$的时间内解决,其中一维枚举r的位长$len$,另一维枚举r的最高位的数字$lim$(这样就轻松解决了它给我们的限制)

    设一位的最大值为$size$,最后答案相当于将$size$个数中大于$lim$的数中选出$len-1$个数按照升序进行排列,即$C_{size-lim}^{len-1}$,最后注意高精度即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch))
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = (ans << 1) + (ans << 3) + (ch ^ 48), ch = getchar();
        while(isdigit(ch));
        return ans * f;
    }
    
    const int MAXN = 600;
    
    const int BITLEN = 10000, BIGSIZE = 53;
    struct Big{
        int val[BIGSIZE], len;
        void operator = (int x){
            memset(val, 0, sizeof(val));
            len = 1, val[1] = x;
        }
        Big(int x = 0){this->operator = (x);}
        Big operator + (Big x){
            Big ans;
            ans.len = max(len, x.len) + 1;
            ans.len = max(ans.len, BIGSIZE - 2);
            for(int i=1; i<=ans.len; i++){
                ans.val[i] += val[i] + x.val[i];
                ans.val[i + 1] += ans.val[i] / BITLEN;
                ans.val[i] %= BITLEN;
            }
            while(ans.len > 1 && ans.val[ans.len] == 0)
                ans.len--;
            return ans;
        }
        void print(){
            for(int i=len; i>=1; i--){
                if(i != len)
                    for(int j=BITLEN/10; j>1; j/=10)
                        if(val[i] < j)
                            putchar('0');
                printf("%d", val[i]);
            }
        }
    };
    
    Big C[MAXN][MAXN];
    
    int main(){
        
        int q = read(), w = read();
        int n = w / q, lim = (1 << (w % q)) - 1, size = (1 << q) - 1;
        if(lim) n++;
        else lim = size;
        Big ans = 0;
        for(int i=0; i<=size+1; i++)
            for(int j=0; j<=i; j++)
                C[i][j] = (j == 0 || i == j) ? 1 : C[i-1][j-1] + C[i-1][j];
        for(int len=2; len<=n; len++){
            int temp = (len == n) ? lim : size;
            for(int i=1; i<=temp && size-i>=len-1; i++)
                ans = ans + C[size-i][len-1];
        }
        ans.print();
        return 0;
    }
    View Code

    T3 Dp[k][i][j]表示两次选择分别选到的纵坐标为i和j,一共进行k步的最大值,转移方程有四块,对应着两个点的左边和右边走来,值得注意的是:for循环内要判断计算出来的x坐标是否超出边界,否则需要将空间开到原来的两倍。其次最后的一步其实没有走到,答案输出最后一个的左边和上面即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch))
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = (ans << 1) + (ans << 3) + (ch ^ 48), ch = getchar();
        while(isdigit(ch));
        return ans * f;
    }
    
    const int MAXN = 101;
    int a[MAXN][MAXN], Dp[MAXN<<1][MAXN][MAXN];
    
    int main(){
        int n = read(), m = read();
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                a[i][j] = read();
        for(int k=2; k<=m+n-2; k++)
            for(int i=1; i<=n; i++)
                for(int j=i+1; j<=n; j++)
                    Dp[k][i][j] = a[i][k-i+1] + a[j][k-j+1] + max(max(Dp[k-1][i][j], Dp[k-1][i-1][j-1]), max(Dp[k-1][i-1][j], Dp[k-1][i][j-1]));
        printf("%d", Dp[m+n-2][n-1][n]);
        return 0;
    }
    View Code

    T4 对于$i<j<k$,且$a_k<a_i<a_j$来说,将$i,j$放到同一个栈是不合法的,枚举每一对不合法的元素,判断是否为二分图,若不是则无法排序,否则直接染色后模拟,按照字典序先后输出结果即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch))
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = (ans << 1) + (ans << 3) + (ch ^ 48), ch = getchar();
        while(isdigit(ch));
        return ans * f;
    }
    
    const int MAXN = 1005;
    int head[MAXN], next[MAXN*MAXN], last[MAXN*MAXN], lineNum;
    void add(int x,int y){
        lineNum++, next[lineNum] = head[x], last[lineNum] = y, head[x] = lineNum;
    }
    
    int a[MAXN], suf[MAXN], col[MAXN];
    
    void DFS(int x,int pre){
        col[x] = 3 - col[pre];
        for(int l=head[x]; l; l=next[l]){
            int y = last[l];
            if(!col[y]) DFS(y, x);
            if(col[y] == col[x]){
                printf("0");
                exit(0);
            }
        }
    }
    
    int st1[MAXN], st2[MAXN], ans[MAXN<<1];
    
    int main(){
        int n = read();
        for(int i=1; i<=n; i++)
            a[i] = read();
        suf[n+1] = 1e9;
        for(int i=n; i>=1; i--)
            suf[i] = min(suf[i+1], a[i]);
        for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++)
            if(a[i] < a[j] && suf[j+1] < a[i])
                add(i, j), add(j, i);
        col[0] = 2;
        for(int i=1; i<=n; i++)
            if(!col[i]) DFS(i, 0);
        for(int i=1, now=1; i<=n; i++){
            if(col[i] == 1) ans[++ans[0]] = 'a', st1[++st1[0]] = a[i];
            else ans[++ans[0]] = 'c', st2[++st2[0]] = a[i];
            while((st1[0] && st1[st1[0]] == now) || (st2[0] && st2[st2[0]] == now)){
                if(st1[st1[0]] == now) ans[++ans[0]] = 'b', st1[0]--, now++;
                if(st2[st2[0]] == now) ans[++ans[0]] = 'd', st2[0]--, now++;
            }
        }
        putchar(ans[1]);
        for(int i=2; i<=ans[0]; i++)
            putchar(' '), putchar(ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    给你的博客园加个面板娘!
    idea实现简单热部署
    idea 上传svn忽略文件
    谈一谈AOP面向切面编程
    做一个自定义注解
    使用aop切面编写日志模块
    数据结构之链表
    数据结构之队列
    数据结构之栈
    数据结构之线性表
  • 原文地址:https://www.cnblogs.com/PHDHD/p/12587584.html
Copyright © 2020-2023  润新知