首页 > 其他分享 >冲刺CSP联训模拟2

冲刺CSP联训模拟2

时间:2024-10-04 18:02:55浏览次数:1  
标签:return 冲刺 llt 括号 联训 us using CSP mod

冲刺CSP联训模拟2

过T2了,赢了

T3 T4 暴力没写满,输了

A 挤压

我是唐诗老哥一个半小时才过 T1

发现要求的是 \(E(s^2)\),因为有个异或,所以直接考虑拆贡献到每一位

\[E(s^2)=E(\sum s_i \sum s_j)=\sum E(s_i s_j) \]

所以直接考虑后面那个咋做,就是 \(i,j\) 位同时是一的时候贡献 \(2^{ij}\) ,发现可以暴力dp做出两位同是一的概率,直接计算期望就完了,是 \(O(n\log^2n)\) 的

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt mod=1e9+7;
const llt N=100100;
llt n,a[N],p[N],ans[40],P[40][40],output,inv;
llt qpow(llt a,llt b)
{
    llt ret=1,mid=a;
    while(b)
    {
        if(b&1) ret=ret*mid%mod;
        mid=mid*mid%mod;
        b>>=1;
    }
    return ret;
}
llt us[N][2][2];
inline llt solve(llt x,llt y)
{
    llt A,B;
    us[0][0][0]=1;
    for(int i=1;i<=n;i++)
    {
        us[i][0][0]=us[i][0][1]=us[i][1][0]=us[i][1][1]=0;
        A=(a[i]>>x)&1,B=(a[i]>>y)&1;
        us[i][0^A][1^B]=us[i][0^A][1^B]+us[i-1][0][1]*p[i]%mod+mod,
        us[i][0][1]=us[i][0][1]+us[i-1][0][1]*(1-p[i])%mod+mod;
        us[i][0^A][0^B]=us[i][0^A][0^B]+us[i-1][0][0]*p[i]%mod+mod,
        us[i][0][0]=us[i][0][0]+us[i-1][0][0]*(1-p[i])%mod+mod;
        us[i][1^A][0^B]=us[i][1^A][0^B]+us[i-1][1][0]*p[i]%mod+mod,
        us[i][1][0]=us[i][1][0]+us[i-1][1][0]*(1-p[i])%mod+mod;
        us[i][1^A][1^B]=us[i][1^A][1^B]+us[i-1][1][1]*p[i]%mod+mod,
        us[i][1][1]=us[i][1][1]+us[i-1][1][1]*(1-p[i])%mod+mod;
        us[i][0][0]%=mod,us[i][0][1]%=mod,us[i][1][0]%=mod,us[i][1][1]%=mod;
    }
    return us[n][1][1];
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%lld",&n);
    for(llt i=1;i<=n;i++)   scanf("%lld",&a[i]);inv=qpow(1e9,mod-2);
    for(llt i=1;i<=n;i++)   scanf("%lld",&p[i]),p[i]=p[i]*inv%mod;
    for(llt i=0;i<=31;i++)
    {
        for(llt j=1;j<=n;j++)
            if((a[j]>>i)&1)
                ans[i]=((1-ans[i])*p[j]%mod+ans[i]*(1-p[j])%mod+mod+mod)%mod;
        output=output+(1ll<<(i*2ll))%mod*ans[i]%mod;output%=mod;
    }
    for(llt i=0;i<=31;i++)
        for(llt j=i+1;j<=31;j++)
                output=output+(1ll<<(i+j+1))%mod*solve(i,j)%mod,output%=mod;
    printf("%lld\n",output);
    return 0;
}

B 工地难题

考虑容斥,直接求最大连续段至少是 \(k\) 的就好了

尝试拿 \(k\) 个 \(1\) 出来,之后还回去,剩下的插板

发现对于一个有 \(x\) 个大于 \(k\) 的连续段的方案恰好计算 \(x\) 遍

所以直接插回去容斥就好了

或者直接转化成 \(n-m+1\) 个自然数相加等于 \(m\),其中最大的数大于等于 \(k\),所以直接容斥成所有的减去全小于 \(k\) 的,就是容斥原理板子(这里求最大连续段小于等于 \(k\) 的可以少一步容斥),预处理组合数,发现是调和级数的, \(O(n \log n)\) 做完了

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt mod=1e9+7;
const llt N=2000100;
llt n,m,inv[N],tms[N],invt[N],us,ans[N],sum,nd;
llt C(llt a,llt b){if(b>a)  return 0;return tms[a]*invt[b]%mod*invt[a-b]%mod;}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    inv[1]=tms[0]=invt[0]=1;for(int i=2;i<=n;i++)  inv[i]=inv[mod%i]*(mod-mod/i)%mod;
    for(int i=1;i<=n;i++)  tms[i]=tms[i-1]*i%mod,invt[i]=invt[i-1]*inv[i]%mod;
    for(int k=m;k>=1;k--)
    {
        nd=0;
        for(int i=k;i<=m;i+=k)
        {
            us=C(m-i+1+n-m-1,n-m);
            if((i/k)&1) nd=(nd+C(n-m+1,i/k)*us%mod+mod)%mod;
            else        nd=(nd-C(n-m+1,i/k)*us%mod+mod)%mod;
        }
        ans[k]=(nd-sum+mod)%mod,sum=(sum+ans[k])%mod;   
    }
    for(int k=1;k<=m;k++)   printf("%lld ",ans[k]);
    return 0;
}

C 星空遗迹

好题啊

发现一些结论:

  1. 我们将相邻两项的胜负关系中胜利看作左括号,失败看作右括号,容易发现如果是合法的括号序列的话答案就是第一个字母,因为括号中间的会被两边吃掉

  2. 如果不满足关系的话,直接找最靠后的一个落单的右括号,发现这个右括号处就是答案,因为合法的括号匹配完毕后可以当做不存在,之后括号序列长这个样子 ))))(((,发现中间的那个一定是答案

那么就可以直接开栈统计,可以做到 \(O(nq)\)

考虑使用数据结构优化,线段树就可行,将左括号设为 \(1\),右括号设为 \(-1\),直接使用线段树维护找那个谷就好了,可以单点修改加线段树二分,也可以维护前缀和,就是后缀修改查区间最小值

复杂度 \(O(q \log n)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt N=2000100;
llt n,q,a,b,w[N],tot,pl;char s[N],c;
int g(char A,char B)
{
    if(A=='R'&&B=='P')  return -1;
    if(A=='P'&&B=='R')  return 1;
    if(A=='P'&&B=='S')  return -1;
    if(A=='S'&&B=='P')  return 1;
    if(A=='R'&&B=='S')  return 1;
    if(A=='S'&&B=='R')  return -1;
    return 0;
}
struct SEGMENT_TREE
{
    llt node[N<<2],sum[N<<2];
    #define mid ((st+ed)>>1)
    llt is,L,R,sigma;
    void change(llt now,llt st,llt ed,llt x,llt p)
    {
        if(st==ed)  {node[now]=min(0ll,p),sum[now]=p;return;}
        if(x<=mid) change(now<<1,st,mid,x,p);
        else       change((now<<1)|1,mid+1,ed,x,p);
        sum[now]=sum[now<<1]+sum[(now<<1)|1];
        node[now]=min(node[now<<1],node[(now<<1)|1]+sum[now<<1]);
    }
    llt find(llt now,llt st,llt ed,llt x,llt y,llt S)
    {
        if(x<=st&&ed<=y){if(S+node[now]<0) {is=now,L=st,R=ed,sigma=S;return sum[now]-node[now];}return S+sum[now];}
        if(x<=mid)  S=find(now<<1,st,mid,x,y,S);
        if(y>mid)   S=find((now<<1)|1,mid+1,ed,x,y,S);
        return S;
    }
    inline llt F(llt x,llt y){if(x+node[y]<0) return sum[y]-node[y];return x+sum[y];}  
    llt check(llt now,llt st,llt ed,llt S)
    {
        if(st==ed)  return st;
        if(node[(now<<1)|1]+F(S,now<<1)<0)    return check((now<<1)|1,mid+1,ed,F(S,now<<1));
        else     return check(now<<1,st,mid,S);
    }
    char Query(llt a,llt b)
    {
        is=L=R=sigma=0;
        find(1,1,n,a,b,0);
        if(is==0)   return s[a];
        return s[check(is,L,R,sigma)+1];
    }
}s_tree;
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%lld%lld",&n,&q);
    scanf("%s",s+1);
    for(int i=1;i<n;i++)    w[i]=g(s[i],s[i+1]),s_tree.change(1,1,n,i,w[i]);  
    for(int i=1;i<=q;i++)   
    {
        scanf("%lld",&a);
        if(a==1)    
        {
            scanf("%lld %c",&b,&c);
            s[b]=c;
            if(b-1>0)   w[b-1]=g(s[b-1],s[b]),s_tree.change(1,1,n,b-1,w[b-1]);
            if(b<n)     w[b]=g(s[b],s[b+1]),s_tree.change(1,1,n,b,w[b]);
        }
        else
        {
            scanf("%lld%lld",&a,&b);
            printf("%c\n",s_tree.Query(a,b-1));
        }
    }
    return 0;
}

D 纽带

我要会这个高低得让 xrlong 给我磕一个

标签:return,冲刺,llt,括号,联训,us,using,CSP,mod
From: https://www.cnblogs.com/hzoi-wang54321/p/18447018

相关文章

  • 10.2 代码源 2024 CSP-S 模拟赛 Day 7
    省流:\(55+5+0+10=70\)简称:唐诗T1第一眼发现在二进制下加法不能进位,然后码了个DP就放那了……DP代码:intS=(1<<14)|1;fd(i,0,r[1])f[1][i]=1;fd(i,2,n){fd(j,0,S){f[i][j]=f[i-1][j];for(ints=j;s;s=(s-1)&j){(f......
  • [题解]P7077 [CSP-S2020] 函数调用
    P7077[CSP-S2020]函数调用题意简述给定一个长度为\(n\)的序列\(a_1,a_2,\dots,a_n\),给定\(m\)个函数,每个函数可能是下面\(3\)种类型,用\(T_x\)表示函数\(x\)的类型:\(T_x=1\),对下标\(p\)增加\(v\)。\(T_x=2\),对所有元素乘\(v\)。\(T_x=3\),由若干类型\(1\)和类型\(2\)组成......
  • CSP-S 2021 廊桥分配
    2021年的提高组第一题学校模拟测试的时候居然想到了AC的代码(((bushiluoguP7913题目意思  大体意思就是有n个廊桥,m1起国内航班,m2起国际航班,国内区和国际区是分开的,把n个廊桥分到两个区,飞机想要尽可能的停在廊桥处,而不停在远机处,每架飞机都有各自的起降时间,廊桥按到达顺序供给......
  • [DMY]2024 CSP-S 模拟赛 Day 7
    题目T1T2T3T4当前分数这场打成一坨了。几乎写的全是暴力。赛时开T1,不太会正解,先写了个暴力丢到那儿。胡了一个\(\mathcal{O}(n^2)\)的做法,但是样例假了,照着手推一遍发现错的很彻底。已经过了1h,于是去看T2。T2还是先写出来了暴力思路。感觉这东西......
  • 冲刺CSP联训模拟2
    冲刺CSP联训模拟2\(T1\)P294.挤压\(40pts\)部分分\(20\%\):爆搜,时间复杂度为\(O(2^{n})\)。另外\(20\%\):观察到值域较小,将值域计入状态设计,时间复杂度为\(O(nV)\)。点击查看代码constllmod=1000000007;lla[100010],p[100010],pp[100010],q[100010],f[2]......
  • 10.4 代码源 2024 CSP-S 模拟赛 Day 9
    省流:\(100+0+0+0=100\)简称:唐诗T1先写了个暴力,然后在想怎么优化,然后想了个区间DP但是写的时候又不会了……然后发现如果这一块数的二进制每一位都有一个数的这一位为\(0\)或者都相同,那么这些数合并起来一定最优,然后双指针搞,复杂度\(O(30n)\)。(这么绕口)赛后听别人说有......
  • [DMY]2024 CSP-S 模拟赛 Day 9
    T2调了1h没调出来,丢了一坨没分的shi扔了。我想放一下作为开头:include<bits/stdc++.h>#defineintlonglongusingnamespacestd;inlineintread(){intw=1,s=0;charch=getchar();while(!isdigit(ch)){if(ch'-')w=-1;ch=getchar();}while(isdigit(ch)){s=s10+(ch-......
  • 【训练记录】2024年莆田市高中信息学奥赛国庆集训CSP-S提高组(第四天场外)
    训练情况rk#1\(100+100+100+100=400\)赛后反思因为满分AK了,就不需要反思了A题显然我们想要选的最多,我们优先选\(a_i\)小的,所以我们对\(a_i\)从小到大排序,再求一个前缀和,再使用二分即可#include<bits/stdc++.h>#defineintlonglongusingnamespaces......
  • CSP-J/S2024总结
    CSP-J/S2024游记初赛前记今年最后一年J了...希望圆我个2年都没有实现的J一等梦还有希望S考好点期待1=day-1考完不放假,然后月考,高兴坏了day1没什么好说的,行就行,不行就AFO(假CSP-J本来就打算摆烂,所以不慌因为是最后一个考场,只有26人,赢!嗯?开局放int?完辣!组合题放那......
  • P9752 [CSP-S 2023] 密码锁&&P8814 [CSP-J 2022] 解密
    GutenTag!Schön,dichzusehen!今天也是很懒惰的一天呢!所以今天三合一!题目:[CSP-S2023]密码锁题目描述小Y有一把五个拨圈的密码锁。如图所示,每个拨圈上是从$0$到$9$的数字。每个拨圈都是从$0$到$9$的循环,即$9$拨动一个位置后可以变成$0$或$8$,因为校园里......