• 【日常摸鱼】ARC113


    【日常摸鱼】ARC113

    前言

    A A*B*C

    水题略了

    B A^B^C

    一个sb题我居然卡了好久。。求(A^{B^C}mod10)直接套扩展欧拉定理就行了

    C String Invasion

    水题略了

    D Sky Reflector

    链接

    https://atcoder.jp/contests/arc113/tasks/arc113_d

    题意

    n行m列的矩阵,每个格子随意填1到k的任意数字,A[i]表示第i行的最小值,B[i]表示第i列的最大值。
    问有多少种不同的{A,B}
    (n,m,kleq 200000)

    题解

    n=1和m=1可以直接特判掉。
    行列都大于1的时候,只需满足max{A[i]}<=min{B[i]}就是合理的方案,然后就是计算了。

    (Code)

    #include <bits/stdc++.h>
    #define LL long long
    #define LD long double
    using namespace std;
    const LL P=998244353;
    const int N=3e5+10;
    const int INF=1e9;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void print(LL x){
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    void pls(LL &x,LL y){
        x+=y;if(x>=P)x-=P;
    }
    LL qpow(LL x,LL y){
        LL re=1;
        while(y){
            if(y&1)re=re*x%P;
            x=x*x%P;y>>=1;
        }
        return re;
    }
    LL n,m,K;
    LL F[200005];
    void MAIN(){
        cin>>n>>m>>K;
        if(n==1&&m==1){
            cout<<K%P<<endl;
            return;
        }
        if(m==1) swap(n,m);
        if(n==1){
            cout<<qpow(K,m)<<endl;
            return;
        }
        if(n>1&&m>1){
            for(LL i=1;i<=K;++i){
                F[i]=qpow(i,n);
            }
            for(LL i=K;i>1;--i){
                F[i]=(F[i]-F[i-1]+P)%P;
            }
            //for(int i=1;i<=K;++i) cout<<F[i]<<" ";cout<<endl;
            LL ans=0;
            for(LL i=1;i<=K;++i){
                ans+=F[i]*qpow(K-i+1,m)%P;
            }
            ans=(ans%P+P)%P;
            cout<<ans<<endl;
            return; 
        }
    }
    
    int main(){
        int ttt=1;
        while(ttt--) MAIN();
        return 0;
    }
    

    E Rvom and Rsrev

    链接

    https://atcoder.jp/contests/arc113/tasks/arc113_e

    题意

    给一个只有a和b的字符串S,每次可以选择两个位置i,j(i<j并且S[i]=S[j]),令字符串的i到j之间的串翻转。可以操作任意次,问能得到的字典序最大的串。多组数据。
    (sum|S|leq 200000)

    题解

    就是个大讨论,具体看代码吧。

    (Code)

    #include <bits/stdc++.h>
    #define LL long long
    #define LD long double
    using namespace std;
    const LL P=998244353;
    const int N=3e5+10;
    const int INF=1e9;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void print(LL x){
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    void pls(LL &x,LL y){
        x+=y;if(x>=P)x-=P;
    }
    LL qpow(LL x,LL y){
        LL re=1;
        while(y){
            if(y&1)re=re*x%P;
            x=x*x%P;y>>=1;
        }
        return re;
    }
    char s[200005];
    int q[200005];
    int tp;
    void MAIN(){
        scanf("%s",s+1);
        int n=strlen(s+1);
        bool flag=0;
        for(int i=1;i<=n;++i) if(s[i]=='a') flag=1;
        if(!flag){
            printf("%s
    ",s+1);
            return;
        }
        flag=0;
        for(int i=1;i<=n;++i) if(s[i]=='b') flag=1;
        if(!flag){
            printf("%s
    ",s+1);
            return;
        }
        if(s[n]=='a'){
            tp=0;int x=0,y=0;
            for(int i=1;i<=n;++i){
                if(s[i]=='a') ++x;
                else {
                    if(x>0){
                        q[++tp]=x;
                        x=0;
                    }
                    ++y;
                }
            }
            if(x>0) q[++tp]=x;
            x=0;
            for(int i=1;i<tp;++i){
                if(q[i]>1) q[tp]=q[tp]+q[i]-2;
                else ++x;
            }
            x=x%2;
            if(x)q[tp]=q[tp]+x-2;
            for(int i=1;i<=y;++i) putchar('b');
            for(int i=1;i<=q[tp];++i) putchar('a');
            puts("");
            return;
        }
        else{
            int x=0,y=0;
            for(int i=n;i>=1;--i){
                if(s[i]=='a') ++x;
                else ++y;
            }
            if(x%2==0){
                for(int i=1;i<=y;++i) putchar('b');puts("");
            }
            else if(s[n-1]=='a'){
                for(int i=1;i<y;++i) putchar('b');
                putchar('a');putchar('b');
                puts("");
            }
            else if(s[n-2]=='a'){
                for(int i=1;i<y-1;++i) putchar('b');
                putchar('a');putchar('b');putchar('b');
                puts("");
            }
            else {
                tp=0;x=0;y=0;
                for(int i=1;i<=n;++i){
                    if(s[i]=='a') ++x;
                    else {
                        if(x>0){
                            q[++tp]=x;
                            x=0;
                        }
                        ++y;
                    }
                }
                if(x>0) q[++tp]=x;
                if(tp==1&&s[1]=='a'){
                    putchar('a');
                    for(int i=1;i<=y;++i) putchar('b');
                    puts("");
                }
                else if(s[1]=='a'&&q[1]>1){
                    x=0;
                    for(int i=1;i<=tp;++i) if(q[i]==1) ++x;
                    if(x==tp-1){
                        q[1]-=1;
                        x-=1;
                        x=x%2;
                        if(x) q[1]-=1;
                        x=q[1];
                    }
                    else{
                        for(int i=2;i<=tp;++i){
                            if(q[i]>1){
                                q[1]=q[1]+q[i]-2;
                            }
                        }
                        x=x%2;
                        if(x) q[1]-=1;
                        x=q[1];
                    }
                    for(int i=1;i<=y-2;++i) putchar('b');
                    for(int i=1;i<=x;++i) putchar('a');
                    puts("");
                }
                else{
                    sort(q+1,q+1+tp);x=0;
                    for(int i=1;i<=tp;++i) if(q[i]==1) ++x;
                    if(x==tp){
                        x=1;
                    }
                    else{
                        for(int i=1;i<tp;++i) if(q[i]>1){
                            q[tp]=q[tp]+q[i]-2;
                        }
                        x=x%2;
                        if(x) q[tp]--;
                        x=q[tp];
                    }
                    for(int i=1;i<=y-2;++i) putchar('b');
                    for(int i=1;i<=x;++i) putchar('a');
                    puts("");
                    
                }
            }
            return;
        }
    }
    
    int main(){
        int ttt;cin>>ttt;
        while(ttt--) MAIN();
        return 0;
    }
    

    F Social Distance

    链接

    https://atcoder.jp/contests/arc113/tasks/arc113_f

    题意

    给n+1个数(x_0,x_1...x_n),现有n个区间([x_0,x_1],[x_1,x_2],[x_2,x_3]..[x_{n-1},x_n])
    在每个区间随机选一个实数,问这n个数最小的距离的期望值。
    (nleq 20)

    题解

    好神的期望题。。。题解看了一整天。。
    首先设(f(z))为最小距离不小于z的概率。
    如果我们知道了(f(z))关于(z)的函数,那么期望值积分一下就算出来了。
    于是问题转化为对于固定值(z),怎么求函数。
    定义n个区间([x_0,x_1],[x_1-z,x_2-z],[x_2-2z,x_3-2z]..[x_{n-1}-(n-1)z,x_n-(n-1)z])
    原问题答案不小于(z)相当于在这n个区间选n个数,并且单调不下降。
    这个新的问题可以DP。
    先把n个区间转化为2n个边界,按顺序排好,(v_1,v_1,v_2,...,v_{2n})
    (dp(i,j,k))表示dp完前i个数,其中最后k个在[v_j,v_{j+1}]区间里,并且满足不下降
    考虑一个转移是(dp(i,j,k)->dp(i+1,j,k+1)),显然就是(dp(i+1,j,k+1)+=dp(i,j,k)*frac{v_{j+1}-v_j}{x_{i+1}-x_{i}}*frac{1}{k+1})
    我们需要的就是最后的(sum_{0leq k leq n}dp(n,2n,k))
    每个(x_{i+1}-x_{i})都是已知的确定值,是常数。(v_{j+1}-v_j)可以写作关于(z)的一次多项式。
    于是最后的答案一定是一个关于(z)的多项式。
    但dp过程跟v的顺序有关,也就是每种顺序都得dp一次,这是个分段函数,段数是(O(n^2))级别的。
    然后dp的时候我们直接设(F_i)为dp完前i个数之后的多项式。
    于是枚举2n个边界,并枚举在这个区间内放k个数,就相当于多项式乘上k次一个关于z的一次多项式,然后除(k!)
    暴力转移即可,最后把(F_n)在可行的z的范围内做积分即可。总效率(O(n^6))

    (Code)

    #include <bits/stdc++.h>
    #define LL long long
    #define LD long double
    using namespace std;
    const LL P=998244353;
    const int N=3e5+10;
    const int INF=1e9;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void print(LL x){
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    void pls(LL &x,LL y){
        x+=y;if(x>=P)x-=P;
    }
    LL qpow(LL x,LL y){
        LL re=1;
        while(y){
            if(y&1) re=re*x%P;
            x=x*x%P;y>>=1;
        }
        return re;
    }
    int n,tot;
    LL X[50],L[50],R[50];
    int p[50];
    LL f[50][50],g[50];
    LL inv[50];
    int l[50],r[50];
    struct node{
        LL x,y;
        LL U,D;
    }a[2000];
    bool cmp(node x,node y){
        return x.U*y.D<x.D*y.U;
    }
    int d0[50],d1[50];
    void MAIN(){
        inv[0]=inv[1]=1;
        for(LL i=2;i<=40;++i)inv[i]=(P-P/i)*inv[P%i]%P;
        for(LL i=2;i<=40;++i)inv[i]=inv[i-1]*inv[i]%P;
        scanf("%d",&n);
        for(int i=0;i<=n;++i) scanf("%lld",&X[i]);
        for(int i=1;i<=n;++i) {
            L[i]=X[i-1];R[i]=X[i];
        }
        tot=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<i;++j)
                for(int k1=0;k1<=1;++k1)
                    for(int k2=0;k2<=1;++k2){
                        ++tot;
                        a[tot].x=i+k1*n;
                        a[tot].y=j+k2*n;
                        a[tot].U=(k1?R[i]:L[i])-(k2?R[j]:L[j]);
                        a[tot].D=i-j;
                    }
        sort(a+1,a+1+tot,cmp);
        p[0]=0;
        for(int i=1;i<=n;++i){
            p[++p[0]]=i;
            p[++p[0]]=i+n;
        }
        LL ans=0;
        for(int now=1;now<tot;++now){
            int flag=0;
            for(int i=1;i<=n*2;++i) if(p[i]==a[now].x){
                for(int j=i+1;j<=n*2;++j) if(p[j]==a[now].y) flag=1;
                if(flag) break;
                for(int j=i;j<n*2;++j) p[j]=p[j+1];
                break;
            }
            if(!flag){
                for(int i=1;i<n*2;++i) if(p[i]==a[now].y){
                    for(int j=n*2;j>i;--j) p[j]=p[j-1];
                    p[i]=a[now].x;
                    break;
                }
            }
            if(a[now].U*a[now+1].D==a[now+1].U*a[now].D) continue;
            for(int i=1;i<=n*2;++i) if(p[i]<=n) l[p[i]]=i;else r[p[i]-n]=i;
            for(int i=2;i<=n;++i) l[i]=max(l[i],l[i-1]);
            for(int i=n-1;i>=1;--i) r[i]=min(r[i],r[i+1]);
            flag=0;
            for(int i=1;i<=n;++i) if(l[i]>=r[i]) {flag=1;break;}
            if(flag) break;
            memset(d0,0,sizeof(d0));
            memset(d1,0,sizeof(d1));
            for(int i=1;i<=n;++i){
                d0[l[i]]=max(d0[l[i]],i);
                d1[r[i]]=max(d1[r[i]],i);
            }
            memset(f,0,sizeof(f));f[0][0]=1;
            int st=1,ed=0;
            for(int i=1;i<n*2;++i){
                ed=max(ed,d0[i]),st=max(st,d1[i]+1);
                if(ed<st) continue;
                for(int j=ed-1;j>=st-1;--j){
                    memcpy(g,f[j],sizeof(g));
                    LL u=(p[i]<=n?p[i]:p[i]-n)-(p[i+1]<=n?p[i+1]:p[i+1]-n);
                    LL v=(p[i+1]<=n?L[p[i+1]]:R[p[i+1]-n])-(p[i]<=n?L[p[i]]:R[p[i]-n]);
                    u=(u%P+P)%P;
                    v=(v%P+P)%P;
                    for(int k=1;k<=ed-j;++k) {
                        for(int t=j+k;t>=1;--t) g[t]=(g[t]*v+g[t-1]*u)%P;
                        g[0]=g[0]*v%P;
                        for(int t=0;t<=j+k;++t) pls(f[j+k][t],g[t]*inv[k]%P);
                    }
                }
            }
            LL x=a[now].U*qpow(a[now].D,P-2)%P;
            LL y=a[now+1].U*qpow(a[now+1].D,P-2)%P;
            for(int i=0;i<=n;++i)
                pls(ans,f[n][i]*qpow((LL)(i+1),P-2)%P*(qpow(y,(LL)(i+1))-qpow(x,(LL)(i+1))+P)%P);
        }
        for(int i=1;i<=n;++i) ans=ans*qpow(X[i]-X[i-1],P-2)%P;
        printf("%lld
    ",ans);
        return;
    }
    
    int main(){
        int ttt=1;
        while(ttt--) MAIN();
        return 0;
    }
    
  • 相关阅读:
    ICE-3.5.1-错误记录
    windows下qtcreator添加ICE库文件
    LINUX下QT与C语言通过网卡名获取网卡IP与MAC
    Apache部署Django+Vue
    三次握手和四次挥手面试常问
    配置mysql时报错
    nosql的介绍以及和关系型数据库的区别
    redis的基本操作
    在Centos安装redis-孙志奇
    git的使用
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/14448503.html
Copyright © 2020-2023  润新知