2018 Multi-University Training Contest 8

Posted shutdown113

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 


以上是关于2018 Multi-University Training Contest 8的主要内容,如果未能解决你的问题,请参考以下文章

2018 Multi-University Training Contest 2

2018 Multi-University Training Contest 9

2018 Multi-University Training Contest 4

2018 Multi-University Training Contest 4

2018 Multi-University Training Contest 3

2018 Multi-University Training Contest 8