首页 > 其他分享 >冲刺国赛模拟 36

冲刺国赛模拟 36

时间:2023-07-14 17:37:07浏览次数:45  
标签:nxt int 36 国赛 -- 冲刺 ans include mod

感觉思想都不难,但是场上不是想不出来就是写不动,见了鬼了。

染色题

考虑一个转化:对于奇数位置,在 \(a_i\neq a_{i+2}\) 的地方放一个红球,对于偶数位置在同样的地方放个蓝球。这样每个区间的限制变成 \([l,r-2]\) 不能同时有红蓝球,转移前缀和优化一下即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
const int mod=998244353;
int n,m,dp[1000010],sum1[1000010],sum2[1000010],a[1000010];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)a[i]=i;
    for(int i=1;i<=m;i++){
        int l,r;scanf("%d%d",&l,&r);
        if(r>=2)a[r-2]=min(a[r-2],l);
    }
    for(int i=n-1;i>=1;i--)a[i]=min(a[i],a[i+1]);
    dp[0]=sum2[0]=1;
    for(int i=1;i<=n;i++){
        if(i&1){
            dp[i]=(sum1[i-1]+sum2[a[i]-1])%mod;
            sum1[i]=(sum1[i-1]+dp[i])%mod;
            sum2[i]=sum2[i-1];
        }
        else{
            dp[i]=(sum2[i-1]+sum1[a[i]-1])%mod;
            sum1[i]=sum1[i-1];
            sum2[i]=(sum2[i-1]+dp[i])%mod;
        }
    }
    int ans=0;
    for(int i=0;i<=n;i++)ans=(ans+dp[i])%mod;
    ans=2ll*ans%mod;
    printf("%d\n",ans);
}

石头剪刀布

先考虑标准淘汰赛的过程怎么处理:设 \(f_{i,j}\) 为 \([i,i+2^j]\) 的胜者,转移容易倍增合并。

然后考虑设 \(g_{i,j}\) 为 \(u\in[i,i+2^j-1]\) 时 \([i,i+2^j-1]\) 的胜者,转移可以根据 \(f\) 得到。

现在考虑回答询问。容易发现一个区间可以拆成 \(\log\) 个 \(g\),剩下的都是 \(f\)。可以类似线段树地分治递归处理。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <unordered_map>
using namespace std;
const int mod=998244353,inv3=(mod+1)/3;
int qpow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=1ll*ans*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return ans;
}
int n,m,trans[3][3],a[300010];
char s[300010];
struct node{
    int a[3];
    node(){memset(a,0,sizeof(a));}
    node operator+(const node&s)const{
        node ans;
        for(int i=0;i<=2;i++)ans.a[i]=(a[i]+s.a[i])%mod;
        return ans;
    }
    node operator*(const node&s)const{
        node ans;
        for(int i=0;i<=2;i++){
            for(int j=0;j<=2;j++){
                ans.a[i]=(ans.a[i]+1ll*a[i]*s.a[j]%mod*trans[i][j])%mod;
                if(i==j)continue;
                ans.a[j]=(ans.a[j]+1ll*a[i]*s.a[j]%mod*trans[j][i])%mod;
            }
        }
        return ans;
    }
}val[3],f[300010][20],g[300010][20];
node query(int L,int R,int l,int r){
    if(l<=L&&R<=r)return g[L][__lg(R-L+2)];
    int mid=(L+R)>>1;
    node val;
    if(l<=mid)val=val+f[mid][__lg(R-mid+1)]*query(L,mid-1,l,r);
    if(mid<r)val=val+f[L][__lg(mid-L+1)]*query(mid+1,R,l,r);
    return val;
}
int main(){
    scanf("%d%d%s",&n,&m,s+1);
    for(int i=1;i<=n;i++){
        if(s[i]=='R')a[i]=0;
        if(s[i]=='P')a[i]=1;
        if(s[i]=='S')a[i]=2;
    }
    trans[0][0]=trans[1][1]=trans[2][2]=1;
    trans[0][1]=trans[1][2]=inv3;trans[0][2]=inv3<<1;
    trans[1][0]=trans[2][1]=inv3<<1;trans[2][0]=inv3;
    val[0].a[0]=val[1].a[1]=val[2].a[2]=1;
    for(int i=1;i<=n;i++)f[i][0]=g[i][1]=val[a[i]];
    for(int j=1;j<=__lg(n)+1;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            f[i][j]=f[i][j-1]*f[i+(1<<j-1)][j-1];
        }
    }
    for(int j=2;j<=__lg(n)+1;j++){
        for(int i=1;i+(1<<j)-2<=n;i++){
            g[i][j]=g[i][j-1]*f[i+(1<<j-1)-1][j-1]+f[i][j-1]*g[i+(1<<j-1)][j-1];
        }
    }
    while(m--){
        int l,r,x,y;scanf("%d%d%d%d",&l,&r,&x,&y);
        int ans=query(l,r,x,y).a[0];
        if(x-l&1)x++;
        ans=1ll*ans*qpow((y-x>>1)+1,mod-2)%mod;
        printf("%d\n",ans);
    }
    return 0;
}

树状数组

首先考虑关键性质:减个 lowbit 之后比 lowbit 低的所有位都变成 \(0\),而高位不会被 lowbit 影响。这意味着我们可以找出使得低位全 \(0\) 在跳一段之后仍然为全 \(0\) 的位置,然后只会跳 \(O(k)\) 次。低位可以预处理每个位置以 \(0\) 开始走到结尾的答案,高位可以直接异或后半段。预处理可以从低位到高位扫,然后每一位从后往前处理,根据之前得到的信息一直跳。

但是这题难度基本全在怎么写。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <unordered_map>
using namespace std;
int n,m,k,A,B;
int nxt[500010][31][2],val[500010],a[500010],ans[500010];
int lowbit(int x){
    return x&-x;
}
int query(int l,int r){
    return val[r]^val[l-1];
}
void calc(int d){
    nxt[n+1][d][0]=n+1;
    for(int i=n;i>=1;i--){
        if(a[i]==-1)nxt[i][d][0]=nxt[i][d][1]=i+1;
        else{
            if(nxt[i][d-1][0]){
                if((query(i,nxt[i][d-1][0]-1)>>d)&1){
                    nxt[i][d][0]=nxt[nxt[i][d-1][0]][d][1];
                    nxt[i][d][1]=nxt[i][d-1][0];
                }
                else{
                    nxt[i][d][0]=nxt[i][d-1][0];
                    nxt[i][d][1]=nxt[nxt[i][d-1][0]][d][1];
                }
            }
        }
    }
}
int find(int x){
    const int U=(1<<k)-1;
    for(int i=k-1;i>=0;i--){
        if(nxt[x][i][0]){
            int ss=(1<<i+1)-1;ss=U^ss;
            return (query(x,n)&ss)|(ans[nxt[x][i][0]]&(U^ss));
        }
    }
    return query(x,n);
}
int lastans;
int getans(int pos,int x){
    const int U=(1<<k)-1;
    for(int i=0;i<k;i++){
        if((x>>i)&1){
            if(!nxt[pos][i][1]){
                int ss=(1<<i)-1;ss=U^ss;
                return ((x^query(pos,n))&ss)|(ans[pos]&(U^ss));
            }
            int ss=(1<<i+1)-1;ss=U^ss;
            x^=query(pos,nxt[pos][i][1]-1)&ss;
            x-=lowbit(x);
            pos=nxt[pos][i][1];
        }
    }
    return ans[pos];
}
int main(){
    scanf("%d%d%d%d%d",&n,&m,&k,&A,&B);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        if(a[i]==-1)val[i]=val[i-1];
        else val[i]=val[i-1]^a[i];
    }
    nxt[n+1][0][0]=n+1;
    for(int i=n;i>=1;i--){
        if(a[i]==-1)nxt[i][0][0]=nxt[i][0][1]=i+1;
        else if(a[i]&1){
            nxt[i][0][0]=nxt[i+1][0][1];
            nxt[i][0][1]=i+1;
        }
        else{
            nxt[i][0][0]=i+1;
            nxt[i][0][1]=nxt[i+1][0][1];
        }
    }
    for(int i=1;i<k;i++)calc(i);
    for(int i=n;i>=1;i--)ans[i]=find(i);
    while(m--){
        int l,x;scanf("%d%d",&l,&x);
        l=l^((1ll*A*lastans+B)%n);x=x^((1ll*A*lastans+B)&((1<<k)-1));
        printf("%d\n",lastans=getans(l,x));
    }
    return 0;
}

标签:nxt,int,36,国赛,--,冲刺,ans,include,mod
From: https://www.cnblogs.com/gtm1514/p/17554544.html

相关文章

  • 360浏览器10是不是把默认字体改成了微软雅黑?怎么能改回宋体?
    360浏览器10是不是把默认字体改成了微软雅黑?怎么能改回宋体?可以在360浏览器,工具---》选项(设置)---》高级设置---》网页设置内自定义字体,修改成看的比较舒服的字体。(如修改成宋体)  在下面改成你喜欢的字体即可。  ......
  • Tita 升级|360 评估问卷库上线
    Tita-OKR和新绩效一体化管理平台1. 新增问卷库模块,快速套用创建360评估活动使用场景:企业之前没有做过360评估活动,不知道如何创建合适的问卷;或者企业想用一些新的问卷进行评估tips:可以直接在问卷库选择合适的模板创建360评估活动,或者创建360评估活动后在问卷页快速套用......
  • 20230718 苏州无人车国赛游寄
    7.14早上4:30起床,5:00打车去机场,5:20左右到机场。弄完机票、安检,突然来短信说飞机时间变了,六点半的飞机改到九点半,在机场一直等着。机场空调有点冷( 8:55发现有人登机了,就跟在队伍后面。9:00准时登机,飞机的颜色蛮漂亮的。......
  • CF1336C(挺重要的区间dp)
    KaaviandMagicSpell-洛谷|计算机科学教育新生态(luogu.com.cn)我们直接考虑如何构造出来的字符串,这个字符串显然只能每次最左端加或者最右端加入。对于第一个字符,显然每个位置都够能放置,且有两种方案。接着下一个字符加入它的左端或者右端,依次类推。令dp[i][j]为s(1......
  • poj 2236 Wireless Network 并查集
    WirelessNetworkTimeLimit: 10000MSMemoryLimit: 65536KTotalSubmissions: 20499Accepted: 8608DescriptionAnearthquaketakesplaceinSoutheastAsia.TheACM(AsiaCooperatedMedicalteam)havesetupawirelessnetworkwiththelapcomputers,butanun......
  • Tita 升级|360 评估能力持续升级
     Tita-OKR和新绩效一体化管理平台1.  支持活动发布后添加被评估人使用场景:360评估活动发布后可以持续添加被评估人2.  新增批量提醒作答功能使用场景:提醒作答时,不想一键提醒所有未评估的人,只想提醒个别人员3.  支持个人分析报告切换显示企业相关数据信息使......
  • 2023冲刺国赛模拟 33.1
    T1染色直接操作分块,可以做到\(O(n\sqrt{n})\)。(显然树剖求lca约为\(O(1)\))code#include<cstdio>#include<algorithm>#include<vector>#include<cstring>usingnamespacestd;constintmax1=1e5,B=300;intn,m;vector<int>......
  • [AGC036F] Square Constraints
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa每个数能取的范围是一段区间\([l_i,r_i]\),其中\(l_i\)单调不增,\(r_i\)单调不增。画个图(\(n=10\)):圆环和矩形的交即为合法点。容易看出\(l_n\)到\(l_{2n-1}\)都是0。本质上是元素有上下界的排列计数,考虑不管下界......
  • 2023 冲刺国赛自测 10
    电脑卡死了然后所有东西都没了,我只能蚌。那重写吧。最近确实感觉挺降智的,许多挺直觉的东西都想不起来了。不知道是不是太情绪化了的影响。见识了H_Kaguya的哈希写法。他的哈希是\(hs_i=hs_{i-1}+s_ip^i\)。才发现博客园个人页面右下角有个回到页首。硬币序列赛时基本会了,......
  • 冲刺国赛模拟 32
    玄学。树赛时以为\(O(mn^22^n),m=200,n=15\)拿头跑\(2s\),结果题解甚至\(m3^n\)跑过……蚌埠了。首先你发现题目要求保留边使得连通的方案数。发现这玩意和\(\ln\)长得类似,于是设\(g_S\)为一个\(m\)次多项式,\(g_{i,S}\)为\(S\)导出子图内选\(i\)条边方案,然后取......