2021牛客多校5(部分题解)

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客多校5(部分题解)相关的知识,希望对你有一定的参考价值。

B.Box

题目大意:每个盒子有01两种可能,打开盒子i要花费wi,也可以选择询问一次花费c,询问可以得知目前未打开的盒子里有多少个1,求得知所有序列的花费最小期望

思路:推式子

当c很大,w都很小时,显然直接打开所有盒子,花费

一般情况下,我们能确定下序列必定是本次盒子后缀全是0或者1,像00011111,然后我本次打开的是最后的那个0盒子,就可以确定下序列,我们算下后缀全是一个数的概率即可,因为我们求要开盒的概率即求不用开当前盒的概率,假设现在在第i个位置,后面还有n-i个盒子,什么时候截止到本次就不用开盒了呢,从i到n都是同色就不用开了,那这样的概率是,那要开的概率就是1-然后就是花费乘期望,就有

 然后和情况一取最小值

算概率的时候,到后面1/2^n其实很小,可以忽略= =

#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <list>
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <deque>
using namespace std;
typedef long long ll;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define scd(v) scanf("%d",&v)
#define scdd(a,b) scanf("%d %d",&a,&b)
#define endl "\\n"
#define IOS ios::sync_with_stdio(false)
#define pb push_back
#define all(v) v.begin(),v.end()
//#define int double
#define odd(x) x&1
#define mst(v,a) memset(v,a,sizeof(v))
#define lson p<<1 ,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
const int N=1e5+10;
int n;
double c;
double a[N];
signed main()
{
    //!!
//   freopen("data.txt","r",stdin);
    //!!
//    IOS;
    cin>>n>>c;
    double sum=0;
    _for(i,1,n) cin>>a[i],sum+=a[i];
    sort(a+1,a+1+n,greater<double>());
    double temp=sum+c;
    double base=1;
    _for(i,1,min(n,60))
    {
       temp -= 1.0*a[i]/base;
       base*=2;
    }
    if( temp < sum )
    {
        printf("%.10lf",temp);
    }
    else printf("%.10lf",sum);
}

D. Double Strings

(题目都读错了

题目大意:两个字符串时好的,如果有相同前缀,一个不同字符(a<b),后缀任意只要长度相同,求方案数

思路:dp、组合数

相同前缀用dp,dp[i][j]表示a串前i个字符与b串前j个字符有多少种相同前缀的匹配方案,

dp[i][j] = dp[i-1][j-1] + dp[i][j-1] + dp[i-1][j] + (a[i] == b[j])*dp[i-1]dp[j-1]

如果当前字符相同,贡献还要加上dp[i-1][j-1]

求后缀的话,假设现在位置在a串第i位。b串第j位,a串还剩len1-i设为x , b还剩len2-j(设为y)位没匹配,接下来挑选任意后缀,不妨设x<=y,则有公式

最后一步,x中选x-i个,y中选i个,一共选x个,所以可以合并

#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <list>
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <deque>
using namespace std;
typedef long long ll;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define scd(v) scanf("%d",&v)
#define scdd(a,b) scanf("%d %d",&a,&b)
#define endl "\\n"
#define IOS ios::sync_with_stdio(false)
#define pb push_back
#define all(v) v.begin(),v.end()
#define int long long
#define odd(x) x&1
#define mst(v,a) memset(v,a,sizeof(v))
#define lson p<<1 ,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
const int N = 1e4 + 10;
const int mod = 1e9 + 7;
int n, m;
int len1, len2;
char s1[N], s2[N];
int dp[5010][5010];
int f[15010];
int ni[15010];
ll qsm(int a, int b)
{
    int ans = 1, temp = a;
    while (b)
    {
        if (b & 1) ans = (ans * temp) % mod; 
        temp = (temp * temp) % mod;
        b>>=1;
    }
    return ans;
}
ll C(int n ,int m)
{
    if( m>n || m<0) return 0;
    if( m==0  || n == m) return 1;
    return f[n] * ni[n-m] %mod * ni[m]%mod;
}
void debug()
{
    cout<<len1<<" len "<<len2<<endl;
}
void solve()
{
    _for(i, 1, len1)
    {
        _for(j, 1, len2)
        {
            dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1];
            if (s1[i] == s2[j]) dp[i][j] += dp[i - 1][j - 1] + 1;
            if(dp[i][j]<0) dp[i][j] += mod;
            if(dp[i][j]>=mod)dp[i][j]%=mod;
        }
    }
    int ans = 0;
    _for(i, 1, len1)
    {
        _for(j, 1, len2)
        {
            if( s1[i] < s2[j] )
            {
               // cout<<i<<" "<<j<<endl;
                int x = len1 - i;
                int y = len2 - j;
                ans += (dp[i-1][j-1]+1) * C(x + y, min(x, y))%mod;
                ans %= mod;
            }
        }
    }
    cout<<ans%mod<<endl;
    //debug();
}
signed main()
{
    //!!
//   freopen("data.txt","r",stdin);
    //!!
    IOS;
    f[0] = 1;
    _for(i, 1, 15000) f[i] = f[i - 1] * i % mod;
    _for(i, 0, 15000) ni[i] = qsm(f[i], mod - 2);
    cin >> (s1 + 1);
    cin >> (s2 + 1);
    len1 = strlen(s1 + 1);
    len2 = strlen(s2 + 1);
    solve();
}

H

我的构造是

010101

010101

101010

101010

K

思路:st表优化+双指针

对于区间而言,极差是有单调性的,如果当前区间满足某极差,对这个区间延伸,极差仍然满足。

枚举区间左界,右界移动指针,右指针找到一个满足位置就停止,下一个左界,右指针不用回头,只要继续右移,这样一遍的复杂度为O(n),总复杂度为O(nm)

st表的查询的log函数需要预处理掉!!被这个坑惨了,一直以为我的st表是O(1)查询,带个log直接tle了。

顺便说一句二分会tle,然后还有单调队列的做法

以上是关于2021牛客多校5(部分题解)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客多校5 B Boxes

2022 牛客多校 Extra & 第九场部分题解

2021牛客多校5 H Holding Two

2022牛客多校1

2022牛客多校1

2022牛客多校1