首页 > 其他分享 >5月3日模拟赛题解(李时珍的皮肤衣 , 马大嘴的废话 , SSY的队列 , 清理牛棚 , 历史の研究)

5月3日模拟赛题解(李时珍的皮肤衣 , 马大嘴的废话 , SSY的队列 , 清理牛棚 , 历史の研究)

时间:2024-05-04 16:11:42浏览次数:25  
标签:std ch SSY int 题解 long zc 马大嘴 getchar

T1 李时珍的皮肤衣

发现是二进制进位,所以直接快速幂即可。

#include<bits/stdc++.h>
#define int __int128
inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    return x*f;
}
const int N=1e6;
int f[N],n;
inline int qpow(int a,int b){
    int ans=1;
    for(;b;b>>=1,a=a*a%n)if(b&1)ans=ans*a%n;
    return ans;
}
signed main(){
    freopen("lsz.in","r",stdin),freopen("lsz.out","w",stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),std::cout.tie(0);
    n=read();
    std::cout<<(long long)((qpow(2,n-1)+1)%n);
}

T2 马大嘴的废话

数据范围小,暴力做或者trie树都可以,卡了单模数哈希,加强版本是P2336 [SCOI2012] 喵星球上的点名 (AC自动机)
hash

#include<bits/stdc++.h>
#define int long long
inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    return x*f;
}
const int N=1e5+10,P=233,mod=1e9+93,mod1=1e9+97;
std::map<std::pair<int,int>,int> mp,un;
int n,m,hs[25],_p[30],_p1[30],hsa[25];
char s[25];
signed main(){
    freopen("mdz.in","r",stdin),freopen("mdz.out","w",stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),std::cout.tie(0);
    std::cin>>n;
    _p[0]=1;_p1[0]=1;
    for(int i=1;i<=25;++i)_p[i]=_p[i-1]*P%mod,_p1[i]=_p1[i-1]*P%mod1;
    for(int i=1;i<=n;++i){
        std::cin>>s+1;
        // std::cout<<s+1<<'\n';
        int len=strlen(s+1);
        for(int j=1;j<=len;++j){
            hs[j]=(hs[j-1]*P%mod+s[j])%mod;
            hsa[j]=(hsa[j-1]*P%mod1+s[j])%mod1;
        }
        for(int r=1;r<=len;++r){
            for(int l=1;l<=r;++l){
                int zc=((hs[r]-hs[l-1]*_p[r-l+1]%mod)%mod+mod)%mod;
                int zc1=((hsa[r]-hsa[l-1]*_p1[r-l+1]%mod1)%mod1+mod1)%mod1;
                if(!un[{zc,zc1}])mp[{zc,zc1}]++,un[{zc,zc1}]=1;
            }
        }
        un.clear();
    }
    std::cin>>m;
    for(int i=1;i<=m;++i){
        std::cin>>s+1;
        int len=strlen(s+1);
        int zc=0,zc1=0;
        for(int j=1;j<=len;++j){
            zc=(zc*P%mod+s[j])%mod;
            zc1=(zc1*P%mod1+s[j])%mod1;
        }
        std::cout<<mp[{zc,zc1}]<<'\n';
    }
}

T3 ssy的队列

有意思的题,学到一个trick,拿哈希划分数来表示状态,然后直接转移即可。
先将序列中的数按模数分类,统计各类数有多少个。
设 \(f_{i,j,v}\) 表示序列排到第 \(i\) 位,最后选的一类数还剩 \(j\) 个,所有类数剩的个数状态为 \(v\) 时的方案数。
因为我们只关注状态的情况,所以第三维状态与顺序无关,这样大大减少了状态数。第三维的总状态只有 \(n\) 的划分数那样多。关于划分数相关知识
然后直接开始枚举,遍历 map,刷表即可。
当n比较大时怎么做?

#include<bits/stdc++.h>
typedef unsigned long long ull;
#define int long long
inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    return x*f;
}
const int N=35,mod=1234567891;
int n,m,a[N],tot,num[N],jc[N];
std::unordered_map<int,int> t;
std::map<std::vector<int>,int> f[N][N];
signed main(){
    freopen("ssy.in","r",stdin);freopen("ssy.out","w",stdout);
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();
    m=read();
    for(int i=1;i<=n;++i){
        a[i]%=m;a[i]=(a[i]+m)%m;
        if(!t[a[i]])t[a[i]]=++tot;
        a[i]=t[a[i]];num[a[i]]++;
    }
    std::vector<int> v;
    for(int i=1;i<=tot;++i)v.push_back(num[i]);
    std::stable_sort(v.begin(),v.end());f[0][0][v]=1;
    for(int i=0;i<n;++i)
        for(int j=0;j<=n;++j)
            for(auto it=f[i][j].begin();it!=f[i][j].end();++it){
                v=it->first;bool vis=0;
                for(int pos=0;pos<v.size();++pos){
                    int x=v[pos];
                    if(!x)continue;
                    if(x==j&&!vis){vis=true;continue;}
                    std::vector<int> zc=v;
                    zc[pos]--;
                    std::stable_sort(zc.begin(),zc.end());
                    f[i+1][x-1][zc]=(f[i+1][x-1][zc]+it->second)%mod;
                }
            }
    jc[0]=1;for(int i=1;i<=n;++i)jc[i]=jc[i-1]*i%mod;
    int ans=1;for(int i=1;i<=tot;++i)ans=ans*jc[num[i]]%mod;
    v.clear();for(int i=1;i<=tot;++i)v.push_back(0);
    std::cout<<ans*f[n][0][v]%mod<<'\n';
}

T4 清理牛棚

一眼可以看出是一个数据结构优化DP之类的东西(也有最短路的巧妙做法)。赛时写了假做法,过了,所以开始口胡
设 \(f_i\) 表示到 \(i\) 时间的最小花费,显然有 \(f_{r_i}=\min(f_{r_k})+s_i(l_i-1\le r_k)\),将牛的相关信息排序后直接拿线段树区间修改查询即可。(代码不贴了)

T5 歴史の研究

出板子题没意思,写的分块,回滚莫队当时直接跳了,等会补。和蒲公英一样。

分块
#include<bits/stdc++.h>
#define int long long
inline int read(){
    char ch=getchar();int x=0,f=1;
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
    return x*f;
}
const int N=1e5+10,LEN=350;
int n,Q,t[LEN][N],len,id[N],temp[N],a[N],mp[N],s[LEN][LEN];
struct BLOCK{int l,r;}blo[LEN];
inline int ask(int l,int r){
    if(id[r]-id[l]<=1){
        int ret=0;
        for(int i=l;i<=r;++i){
            mp[a[i]]++;
            ret=std::max(ret,mp[a[i]]*temp[a[i]]);
        }
        for(int i=l;i<=r;++i)mp[a[i]]=0;
        return ret;
    }
    else{
        int ans=s[id[l]+1][id[r]-1];
        for(int i=l;id[i]==id[l];++i){
            mp[a[i]]++;
            int cnt=t[id[r]-1][a[i]]-t[id[l]][a[i]];
            ans=std::max(ans,(mp[a[i]]+cnt)*temp[a[i]]);
        }
        for(int i=r;id[i]==id[r];--i){
            mp[a[i]]++;
            int cnt=t[id[r]-1][a[i]]-t[id[l]][a[i]];
            ans=std::max(ans,(mp[a[i]]+cnt)*temp[a[i]]);
        }
        for(int i=l;id[i]==id[l];++i)mp[a[i]]=0;
        for(int i=r;id[i]==id[r];--i)mp[a[i]]=0;
        return ans;
    }
}
signed main(){
    // freopen("a.in","r",stdin),freopen("a.out","w",stdout);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),std::cout.tie(0);
    n=read();len=std::sqrt(n);Q=read();
    for(int i=1;i<=n;++i){
        id[i]=(i-1)/len+1;
        if(id[i]!=id[i-1])blo[id[i]].l=i;
        blo[id[i]].r=i;
        temp[i]=a[i]=read();
    }
    std::stable_sort(temp+1,temp+n+1);
    int _len=std::unique(temp+1,temp+n+1)-temp-1;
    for(int i=1;i<=n;++i)a[i]=std::lower_bound(temp+1,temp+_len+1,a[i])-temp;
    for(int k=1;k<=id[n];++k){
        for(int i=1;i<=_len;++i)t[k][i]=t[k-1][i];
        for(int i=blo[k].l;i<=blo[k].r;++i)t[k][a[i]]++;
    }
    for(int i=1;i<=id[n];++i){
        for(int j=i;j<=id[n];++j){
            int max=s[i][j-1];
            for(int k=blo[j].l;k<=blo[j].r;++k){
                int cnt=t[j][a[k]]-t[i-1][a[k]];
                max=std::max(max,cnt*temp[a[k]]);
            }
            s[i][j]=max;
        }
    }
    for(int i=1;i<=Q;++i){
        int l=read(),r=read();
        std::cout<<ask(l,r)<<'\n';
    }
}
回滚莫队

标签:std,ch,SSY,int,题解,long,zc,马大嘴,getchar
From: https://www.cnblogs.com/Ishar-zdl/p/18172418

相关文章

  • 题解:ssy的队列
    题目链接题目描述SSY是班集体育委员,总喜欢把班级同学排成各种奇怪的队形,现在班级里有\(N\)个身高互不相同的同学,请你求出这\(N\)个人的所有排列中任意两个相邻同学的身高差均不为给定整数\(M\)的倍数的排列总数。输入格式共三行:第一行为\(N\)第二行为\(N\)个不同的......
  • P10064 [SNOI2024] 公交线路 题解
    弱化版:CF1827EBusRoutes。对于\(n=2\)的情况可以判掉,剩下的情况取一个度数大于一的点作为根。首先发现如果叶子间满足条件,那么整棵树也满足条件。考虑叶子间什么时候满足条件,记点\(x\)通过最多一条路径可以到达的所有点的集合为\(S_x\),则需满足\(\forallx,y\in\mathbf......
  • [国家集训队] 矩阵乘法 题解
    发现实际上就是二维静态区间最大值,可以用整体二分维护。时间复杂度\(O((q+n^2)\log\max(a_{i,j})\logn^2)\)。#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintW=310005;constintQ=6e4+5;intn,q,w,ans[Q];intc[505][505],m;voidadd(i......
  • 题解【[ABC147F] Sum Difference】
    题目链接下为口胡题解:入手方向推导:直接考虑题目所给式子显然困难:\[w(S)=\sum_{i\inS}A_i-\sum_{i\notinS}A_i\]因为两个式子虽然相关但是都在变化,不妨转化为:\[w(S)=2\times\sum_{i\inS}A_i-\sum_{i=1}^nA_i\]这样只用求出有多少个不同的\(\sum_{i\inS}A_i\)。由于......
  • CF1968E.Cells Arrangement-构造(给个和题解不同的做法)
    link:https://codeforces.com/problemset/problem/1968/E题意:需要构造一个\(n\timesn\)的棋盘,在上面放\(n\)枚棋子,设集合\(\mathcal{H}\)表示两两之间曼哈顿距离构成的集合,要让\(|\mathcal{H}|\)最大。给出放棋子的方案。首先说说题解的做法…考虑把距离为奇数和偶数的......
  • 题解:CF1926G
    题目传送门思路发现权值为C的点可以选择看做是权值为S或为P的点,所以问题转换为怎么给C点赋值可以使答案最小,考虑树形dp。\(f_{i,0/i,1}\)表示\(i\)点赋值为S或P时最少要删除几条边。但如果当前点权值不为C的话,那显然他的父亲节点应该选择和他权值相同的点才......
  • 题解:AT_abc298_h [ABC298Ex] Sum of Min of Length
    分析模拟赛签到题。考虑分讨。分两种情况:\(L=R\)。\(L\neR\)。对于第\(1\)种情况,用换根DP求一个\(i\)为根时所有点的深度和就行。对于第\(2\)种情况,钦定$dep_R\gedep_L$。很显然,\(R\)为根的子树中所有点都是离\(R\)更近。假设在\(L\)到\(R\)的路径......
  • 题解【[ABC077D] Small Multiple】
    题目链接题意简述:给定正整数\(K\),求数位之和最小的\(K\)的倍数的数位和。错误方向:\(K\)的倍数一定满足\(K\timesS\),根据\(K\)的特征构造出合适的\(S\)。正确方向考虑直接构造出K的倍数,由于从1开始可以通过×10和+1构造出所有数字,并且在此......
  • 【题解】P4711 「化学」相对分子质量
    Problem给定一个长度为\(L\)的化学式,求出此化学式的相对分子质量。例:十二水合硫酸铝钾(明矾)\(KAl(SO_4)_2\cdot12H_2O\).输入格式形为:KAl(SO_{4})_{2}~12H_{2}OSolve清新小模拟。定义一下“结账”这个概念,分为三种:原子结账,即为当单独的一个(一坨)原子计算完成后,计入所属......
  • [题解]ABC337E Bad Juice
    ABC337EBadJuice一开始的想法如下:就是利用二分法,对于一个区间\([l,r]\),分成\([l,mid-1],[mid,r-1]\)两部分,各找两个朋友喝,右边还空出一个\(r\),如果前面两个朋友都没中毒,那说明\(r\)这瓶有毒。但仔细一想,我们发现\([1,n)\)的瓶子中任意一个我们分出的区间\([l,r]\),都用去了\(......