zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 8

    Character Encoding

    题意:

      随机挑出m个数字,满足每个数字位于【0,n-1】区间内且所有数相加等于k,问一共有多少种选法?

    分析:

      不难看出该题目可以变换成将k个1分成m块的个数,即在k个1中插m-1个板子,根据隔板法,放的方法数有C(k+m-1,m-1)。考虑分块后有的块所有数字相加和超过n-1,需要去掉这种特殊情况。假设一共有i块>=n,那么x1+x2+x3……+xm=k,等式两边同时减去i*n,这样等式就变成了x1'+x2'+……+xm'=k-i*n。因为违反规定的i块都减去了n,所以违反规定的块的范围就从>=n,变成了>=0,而x1'+x2'+……+xm'=k-i*n式子的含义将k-i*n个1分成m块的个数,为C(k-i*n+m-1,m-1),最后用容斥原理去掉重复计算的情况就好了。

      参考博客:大佬博客

    代码:

    #include <queue>
    #include <vector>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=2e5+100;
    const int mod=998244353;
    
    int n,m,k,T;
    
    ll fac[maxn],inv[maxn];
    
    ll poww(ll a,int k)
    {
        ll res=1;
        while(k)
        {
            if(k&1) res=res*a%mod;
            a=a*a%mod;
            k>>=1;
        }
        return res;
    }
    
    void getinv()
    {
        fac[0]=fac[1]=1;
        for(int i=2;i<maxn;i++){
            fac[i]=fac[i-1]*i%mod;
        }
        inv[maxn-1]=poww(fac[maxn-1],mod-2);
        for(int i=maxn-2;i>=0;i--){
            inv[i]=inv[i+1]*(i+1)%mod;
        }
    }
    
    ll C(int n,int m)
    {
        if(m>n) return 0;
        return fac[n]*inv[n-m]%mod*inv[m]%mod;
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
        #endif // ONLINE_JUDGE
        getinv();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d %d",&n,&m,&k);
    
            ll ans=0;
            int sign=-1;
            for(int i=0;i<=k/n;i++){
                sign=-sign;
                ans=(ans+sign*C(m,i)*C(m-1+k-i*n,m-1)%mod+mod)%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    Parentheses Matrix

    题意:

      如果空串为平衡串;如果A是平衡的,name(A)也是平衡的;如果A,B是平衡的,那么AB是平衡的。定义矩阵的godness值,为矩阵的平衡的行和列的个数。给出矩阵的行列,要求构造godness值最大的矩阵。

    分析:

      如果矩阵的行列值都为奇数,那么godness一定为0,随意输出就好。

      如果矩阵的行列值一个为奇数,一个为偶数,那么就让为偶数的平衡就好了。

      如果矩阵的行列值都为偶数,考虑两种构造方法,一种是先让行(列)先满足,然后再尽量去匹配列(行),godness值为max(n+m/2-1,m+n/2-1)。另一种是让行列匹配相加和尽可能多,godness值为n+m-4。

    代码:

    #include <queue>
    #include <vector>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=500;
    
    char graph[maxn][maxn];
    
    int n,m,T;
    
    void solve_n()
    {
        for(int i=1;i<=n;i++){
            if(i<=n/2){
                graph[i][1]='(';
                graph[i][m]=')';
                for(int j=2;j<m;j++){
                    if(j%2==0)  graph[i][j]='(';
                    else        graph[i][j]=')';
                }
            }
            else {
                for(int j=1;j<=m;j++){
                    if(j%2==1)  graph[i][j]='(';
                    else        graph[i][j]=')';
                }
            }
        }
    }
    
    void solve_m()
    {
        for(int j=1;j<=m;j++){
            for(int i=1;i<=n;i++){
                if(j<=m/2){
                    if(i%2==0)  graph[i][j]='(';
                    else        graph[i][j]=')';
                    if(i==1)    graph[1][j]='(';
                    else if(i==n)   graph[n][j]=')';
                }
                else{
                    if(i%2==1)  graph[i][j]='(';
                    else        graph[i][j]=')';
                }
            }
        }
    }
    
    void solve()
    {
        for(int j=1;j<=m;j++)   graph[1][j]='(',graph[n][j]=')';
        for(int i=2;i<n;i++){
            if(i%2==0){
                for(int j=1;j<=m;j++){
                    if(j%2==1)  graph[i][j]='(';
                    else        graph[i][j]=')';
                }
            }
            else {
                graph[i][1]='(';
                graph[i][m]=')';
                for(int j=2;j<m;j++){
                    if(j%2==0)  graph[i][j]='(';
                    else        graph[i][j]=')';
                }
            }
        }
    }
    
    void print()
    {
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                printf("%c",graph[i][j]);
            }
            printf("
    ");
        }
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&n,&m);
            if(n%2==0&&m%2==0){
                if(n>2&&m>2&&n+m-4>max(n+m/2-1,m+n/2-1)){
                    solve();
                }
                else {
                    if(n>m) solve_n();
                    else     solve_m();
                }
            }
            else if(n%2==0) solve_m();
            else if(m%2==0) solve_n();
            else            solve_n();
            print();
        }
        return 0;
    }
    View Code

    Magic Square

    题目:

      给出两种操作,顺时针旋转(逆时针旋转)一个矩阵,最后输出总矩阵。

    分析:

      直接模拟就好。

    代码:

    include <queue>
    #include <vector>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=1e5+100;
    
    int g[10][10];
    
    void spin_c(int x)
    {
        int r=(x>2?2:1);
        int c=(x%2==1?1:2);
        int tmp=g[r][c];
        g[r][c]=g[r+1][c];
        g[r+1][c]=g[r+1][c+1];
        g[r+1][c+1]=g[r][c+1];
        g[r][c+1]=tmp;
    }
    
    void spin_r(int x)
    {
        int r=(x>2?2:1);
        int c=(x%2==1?1:2);
        int tmp=g[r][c];
        g[r][c]=g[r][c+1];
        g[r][c+1]=g[r+1][c+1];
        g[r+1][c+1]=g[r+1][c];
        g[r+1][c]=tmp;
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int n,T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=3;i++){
                for(int j=1;j<=3;j++){
                    scanf("%1d",&g[i][j]);
                }
            }
            for(int i=1;i<=n;i++){
                int id;
                char ch;
                scanf("%d%c",&id,&ch);
                if(ch=='C') spin_c(id);
                else if(ch=='R')    spin_r(id);
            }
            for(int i=1;i<=3;i++){
                for(int j=1;j<=3;j++){
                    printf("%d",g[i][j]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    View Code

    Taotao Picks Apples

    题意:

      给出两种操作,修改序列的第x个值为y,询问这个序列的最长上升子序列的长度。

    分析:

      一共看了两种做法,线段树ST+dp,感觉大佬讲的贼详细。

    代码:

    线段树

    #include <map>
    #include <queue>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=1e5+100;
    
    int n,q,T;
    
    int arr[maxn];
    
    namespace IntervalTree {
        #define lson l,m,rt<<1
        #define rson m+1,r,rt<<1|1
        int cnt[maxn<<2],maxx[maxn<<2];
        int query(int v,int l,int r,int rt)
        {
            if(l==r)    return maxx[rt]>v;
            if(maxx[rt]<=v)  return 0;
    
            int m=(l+r)>>1;
            if(maxx[rt<<1]<=v)  return query(v,rson);
            else                return cnt[rt]-cnt[rt<<1]+query(v,lson);
        }
        void PushUp(int l,int r,int rt)
        {
            int m=(l+r)>>1;
            maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
            cnt[rt]=cnt[rt<<1]+query(maxx[rt<<1],rson);
        }
        void build(int l,int r,int rt)
        {
            if(l==r){
                cnt[rt]=1;
                maxx[rt]=arr[l];
                return;
            }
            int m=(l+r)>>1;
            build(lson);
            build(rson);
            PushUp(l,r,rt);
        }
        void update(int p,int c,int l,int r,int rt)
        {
            if(l==r){
                cnt[rt]=1;
                maxx[rt]=c;
                return;
            }
            int m=(l+r)>>1;
            if(p<=m)    update(p,c,lson);
            else        update(p,c,rson);
            PushUp(l,r,rt);
        }
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
        #endif // ONLINE_JUDGE
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&n,&q);
            for(int i=1;i<=n;i++){
                scanf("%d",&arr[i]);
            }
    
            IntervalTree::build(1,n,1);
            for(int i=1;i<=q;i++){
                int x,y;
                scanf("%d %d",&x,&y);
                int pre=arr[x];
                IntervalTree::update(x,y,1,n,1);
                printf("%d
    ",IntervalTree::query(-1,1,n,1));
                IntervalTree::update(x,pre,1,n,1);
            }
        }
        return 0;
    }
    View Code

    ST+dp

    #include <map>
    #include <queue>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=1e5+100;
    
    int n,q,T;
    
    int arr[maxn],dp[2][maxn];
    
    namespace ST {
        const int maxlog=30;
        int d[maxn][maxlog];
        void init(int n)
        {
            for(int i=1;i<=n;i++)    d[i][0]=i;
            for(int j=1;(1<<j)<=n;j++){
                for(int i=1;i+(1<<j)-1<=n;i++){
                    int L=d[i][j-1],R=d[i+(1<<(j-1))][j-1];
                    if(arr[L]>=arr[R])   d[i][j]=L;
                    else                 d[i][j]=R;
                }
            }
        }
        int query(int L,int R)
        {
            if(R<L) return 0;
            int k=0;
            while((1<<(k+1))<=R-L+1)    k++;
            int l=d[L][k],r=d[R-(1<<k)+1][k];
            if(arr[l]>=arr[r])   return l;
            return r;
        }
    };
    
    int binary_Search(int p,int key)
    {
        int l=p+1,r=n;
        if(arr[ST::query(l,r)]<=key||l>r)  return 0;
        while(l<r)
        {
            int mid=l+(r-l)/2;
            if(arr[ST::query(l,mid)]>key)  r=mid;
            else    l=mid+1;
        }
        return r;
    }
    
    void initdp()
    {
        int pos=1;
        dp[0][1]=1;
        for(int i=2;i<=n;i++){
            if(arr[i]>arr[pos]){
                dp[0][i]=dp[0][pos]+1;
                pos=i;
            }
            else dp[0][i]=-1;
        }
    
        dp[1][n]=1;
        for(int i=n-1;i>=1;i--){
            int p=binary_Search(i,arr[i]);
            if(p&&arr[p]>arr[i])   dp[1][i]=dp[1][p]+1;
            else                   dp[1][i]=1;
        }
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
        #endif // ONLINE_JUDGE
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&n,&q);
            for(int i=1;i<=n;i++){
                scanf("%d",&arr[i]);
            }
    
            ST::init(n);
            initdp();
            for(int i=1;i<=q;i++){
                int x,y,ans=0;
                scanf("%d %d",&x,&y);
                int p=ST::query(1,x-1),mx=arr[p];
                ans+=dp[0][p];
                if(y>arr[p]){
                    ans++;
                    mx=y;
                }
                p=binary_Search(x,mx);
                if(p&&arr[p]>mx)   ans+=dp[1][p];
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Ultra-QuickSort(归并排序求逆序对数)
    Power Network (最大流增广路算法模板题)
    Sorting It All Out
    Asteroids(二分图最大匹配模板题)
    昂贵的聘礼
    Borg Maze(bfs+prim)
    Currency Exchange(判断是否有正环)
    Children of the Candy Corn (bfs+dfs)
    Tautology
    Flip Game
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9514525.html
Copyright © 2011-2022 走看看