【日常摸鱼】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,k\leq 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\n",s+1);
        return;
    }
    flag=0;
    for(int i=1;i<=n;++i) if(s[i]=='b') flag=1;
    if(!flag){
        printf("%s\n",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个数最小的距离的期望值。
\(n\leq 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_{0\leq 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\n",ans);
    return;
}

int main(){
    int ttt=1;
    while(ttt--) MAIN();
    return 0;
}
posted @ 2021-02-25 18:15  Iscream-2001  阅读(164)  评论(0编辑  收藏  举报
/* */ /* */