其他分享
首页 > 其他分享> > 【日常摸鱼】牛客挑战赛3

【日常摸鱼】牛客挑战赛3

作者:互联网

【日常摸鱼】牛客挑战赛3

前言

A 珂学送分

期望dp,要用前缀和优化一下。。略了

B 遇见

比较水的追及问题。。。但是两个点一开始就在一起要特判掉。

C 位数差

稍微转化一下。。只用求数列中任意两对数的和的位数,这个可以随便套数据结构。

D 蝴蝶

思路大致跟上一场蝴蝶差不多。。而且比上场那个简单多了,连数据结构都不用套。。

E 迷宫

还没写。。

F 01序列

链接

https://ac.nowcoder.com/acm/contest/20/F

题意

给定长度为 n 的01序列,序列中部分位置已经确定,剩余部分01等概率出现。对最终序列求最长不下降序列(如有多种可能序列,则在此基础上最大化1的个数),设最长不下降序列的长度为 len,最长不下降序列中1的个数为 num,求期望 E(len * num) * 2 ^ 10000 对 1000000007 取模的结果。
\(n\leq 1000\)

题解

后面乘的2^10000没什么用,只是把前面E的分母都抵消了而已。。
于是我们要算的就是所有情况的len*num的总和。。
我们先考虑对已知序列,怎么求1最多的最长不下降子序列。。
最终的子序列必然是一段0和一段1。。。
我们从左往右依次考虑,假设当前序列的最优解是前面一段0,然后从第i个位置开始全选1。。
如果后面再放个1,直接取过来就行。。
如果后面放个0,如果从i开始的1的个数不少于0的个数,那么什么都不用做。
如果放0后,从i开始的0的个数大于1的个数,那么这一段全选0的长度一定优于全选1。于是这部分的1全部舍弃掉。
这个过程我们很容易能用dp来维护。。于是这题就做完了。

\(Code\)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=1e9;
const int N=1e3+100;
const LL P=1000000007;
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;
}
int n;
int a[N];
LL len[N][N],num[N][N],cnt[N][N],dp[N][N];
int main(){
    int tt=10000;
    n=read();
    for(int i=1;i<=n;++i) a[i]=read();
    cnt[0][0]=1;
    for(int i=0;i<n;++i){
        if(a[i+1]==-1) --tt;
        for(int j=0;j<=i;++j){
            if(a[i+1]!=1){
                if(j>0) {
                    pls(len[i+1][j-1],len[i][j]);
                    pls(cnt[i+1][j-1],cnt[i][j]);
                    pls(num[i+1][j-1],num[i][j]);
                    pls(dp[i+1][j-1],dp[i][j]);
                }
                else{
                    pls(len[i+1][j],(cnt[i][j]+len[i][j])%P);
                    pls(cnt[i+1][j],cnt[i][j]);
                }
            }
            if(a[i+1]!=0){
                pls(len[i+1][j+1],(cnt[i][j]+len[i][j])%P);
                pls(cnt[i+1][j+1],cnt[i][j]);
                pls(num[i+1][j+1],(num[i][j]+cnt[i][j])%P);
                pls(dp[i+1][j+1],(dp[i][j]+num[i][j]+len[i][j]+cnt[i][j])%P);
            }
        }
    }
    LL ans=0;
    for(int i=0;i<=n;++i) pls(ans,dp[n][i]);
    ans=(ans%P+P)%P;
    for(int i=1;i<=tt;++i) pls(ans,ans);
    printf("%lld\n",ans);
    return 0;
}

标签:cnt,pls,int,len,牛客,num,摸鱼,序列,挑战赛
来源: https://www.cnblogs.com/Yuigahama/p/14397740.html