首页 > 其他分享 >20241003 模拟赛

20241003 模拟赛

时间:2024-10-04 18:01:31浏览次数:6  
标签:20241003 int ll pers return segment 模拟 out

这场...打得还行吧。(至少没有爆零



A. 旋律的总数

难度:橙
签到题。
只要第一个都选 \(1\),就能保证不同。
答案为 \(m^{n-1}\)。

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
int T;
ll n,m;
ll quickpow(ll a,ll b){
    ll ret=1,base=a;
    while(b){
        if(b&1)ret=ret*base%mod;
        base=base*base%mod;
        b>>=1;
    }
    return ret;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    // freopen("sum.in","r",stdin);
    // freopen("sum.out","w",stdout);
    cin>>T;
    while(T--){
        cin>>n>>m;
        cout<<quickpow(m,n-1)<<'\n';
    }
    return 0;
}

B. 水果加工

难度:绿-蓝
正解用的背包,我打的暴力+卡时75pts。
但我们聪明的机房大神懒得想那么多,折半搜索(meet in the middle)搞定!

#include<bits/stdc++.h>
#define ll long long 
#define pii pair<ll,ll>
using namespace std;
const ll N=45;
ll n,a[N],b[2],c[2][N],d[2][N],u[2][N],mid;
vector<pii>vec[N][N],w[N][N];
vector<pii>vec2[N][N],w2[N][N];
/*
dfs传的参代表的含义
x:第 x 个农场
sum1:所有水果均运输完毕的时间
sum2:所有工厂完成加工的时间
cnt1:工厂 1 用掉的机器
cnt2:工厂 2 用掉的机器
*/
void dfs(ll x,ll sum1,ll sum2,ll cnt1,ll cnt2){
    if(x>n/2){
        vec[cnt1][cnt2].push_back({sum1,sum2});
        return;
    }
    //这段代码的含义:vec2[第一个工厂用了cnt1个机器][第二个工厂用了cnt2个机器]
    //.push_back({工厂1完成加工的总时间, 工厂2完成加工的总时间});
    //就相当于存一下搜到的状态
    for(ll i=0;i<=a[x];i++){//对于每个农场 x,第一个工厂分到 i 吨,则第二个工厂分到 (a[x] - i) 吨
		if(c[0][x]*(i!=0)+cnt1<=b[0]&&c[1][x]*(i!=a[x])+cnt2<=b[1]){
			ll mx1=max(sum1,max(d[0][x]*i,d[1][x]*(a[x]-i)));
			ll mx2=max(sum2,max(u[0][x]*i,u[1][x]*(a[x]-i)));
			ll mx3=cnt1+c[0][x]*(i!=0);
            //加上工厂 1 用掉的机器,i = 0 时第一个工厂不需要开生产线(因为没有分给第一个工厂的)
			ll mx4=cnt2+c[1][x]*(i!=a[x]);
            //加上工厂 2 用掉的机器,i = a[x] 时第二个工厂不需要开生产线
			dfs(x+1,mx1,mx2,mx3,mx4);   	
    	}
    }
}
void dfs2(ll x,ll sum1,ll sum2,ll cnt1,ll cnt2){
    if(x>n){
        vec2[cnt1][cnt2].push_back({sum1,sum2});
        return;
    }
    for(ll i=0;i<=a[x];i++){
		if(c[0][x]*(i!=0)+cnt1<=b[0]&&c[1][x]*(i!=a[x])+cnt2<=b[1]){
			ll mx1=max(sum1,max(d[0][x]*i,d[1][x]*(a[x]-i)));
			ll mx2=max(sum2,max(u[0][x]*i,u[1][x]*(a[x]-i)));
			ll mx3=cnt1+c[0][x]*(i!=0);
			ll mx4=cnt2+c[1][x]*(i!=a[x]);
			dfs2(x+1,mx1,mx2,mx3,mx4);   	
    	}
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
//    freopen("fruit.in","r",stdin);
//    freopen("fruit.out","w",stdout);
	cin>>n;
    for(ll i=1;i<=n;i++)cin>>a[i];
    cin>>b[0]>>b[1];
	for(ll i=1;i<=n;i++)cin>>c[0][i];for(ll i=1;i<=n;i++)cin>>c[1][i];
	for(ll i=1;i<=n;i++)cin>>d[0][i];for(ll i=1;i<=n;i++)cin>>d[1][i];
	for(ll i=1;i<=n;i++)cin>>u[0][i];for(ll i=1;i<=n;i++)cin>>u[1][i];
	mid=n/2;
    dfs(1,0,0,0,0); 
    dfs2(n/2+1,0,0,0,0);
    for(ll i=0;i<=b[0];i++){
        for(ll j=0;j<=b[1];j++){
            sort(vec[i][j].begin(),vec[i][j].end());
            vector<pii> tmp;
            ll si=vec[i][j].size();
            for(ll x=0;x<si;x++)
                if(!x||vec[i][j][x].first!=vec[i][j][x-1].first) 
                    tmp.push_back(vec[i][j][x]);
            si=tmp.size();
            for(ll x=0;x<si;x++)
                if(!x||tmp[x].second<tmp[x-1].second) 
                    w[i][j].push_back(tmp[x]);
        }
    }
    for(ll i=0;i<=b[0];i++){
        for(ll j=0;j<=b[1];j++){
            sort(vec2[i][j].begin(),vec2[i][j].end());
            vector<pii>tmp;
            ll si=vec2[i][j].size();
            for(ll x=0;x<si;x++) 
                if(!x||vec2[i][j][x].first!=vec2[i][j][x-1].first) 
                    tmp.push_back(vec2[i][j][x]);
            //去掉一些重复状态,first第一次出现时,此时的second肯定是最小的,因此保留第一个出现的。
            si=tmp.size();
            for(ll x=0;x<si;x++) 
                if(!x||tmp[x].second<tmp[x-1].second) 
                    w2[i][j].push_back(tmp[x]);
            //此时first是递增的,当且仅当此时的 se 小于前一个的 se 才有可能成为答案
        }
    }
    ll ans=1e18;
    for(ll i=0;i<=b[0];i++)
        for(ll j=0;j<=b[1];j++)
            for(ll k=0;k<=b[0]-i;k++)
                for(ll l=0;l<=b[1]-j;l++) 
                    for(auto x:w[i][j])
                        for(auto y:w2[k][l])
                            ans=min(ans,max(x.first,y.first)+max(x.second,y.second));
    cout<<ans;
    return 0;
}

C. 最佳位置

难度:绿-蓝
打的暴力寄了...
最初想法是搞一个空段的结构体,用set维护区间长度,但细想发现删除操作很难搞,于是考虑再来一个set维护坐的位置。

#include<bits/stdc++.h>
#define ll long long
#define mxn 300010
#define pb push_back
using namespace std;
ll n,m,seat[mxn];//编号i的人所坐的位置
struct segment{//空段,包含了[begin,end]这一整段
    int l,r;
    int get_max()const{
        if(l==1)return 1;//如果是最左边,肯定选最左边的 
        else if(r==n)return n;//如果是最右边,肯定选最右边的
        else return (l+r)/2;
    }
    int len()const{
        if(l!=1&&r!=n)return (r-l+2)/2;
        else return r-l+1;//如果begin==1&&end==n,则全场都空着,会来到位置1.
    }    
    segment(int _l,int _r){
        l=_l,r=_r;
    }
};
struct num_cmp{
    bool operator()(const segment &a,const segment &b)const{
        return a.l<b.l;
    }
};
struct len_cmp{
    bool operator()(const segment &a,const segment &b)const{
        if(a.len()==b.len())return a.l<b.l;
        else return a.len()>b.len();
    }
};
bool operator!=(const segment &a,const segment &b){
    return a.l!=b.l||a.r!=b.r;
}
bool operator==(const segment &a,const segment &b){
    return !(a!=b);
}
set<segment,num_cmp> numset; //一个按开始位置
set<segment,len_cmp> lenset; //一个按距离
void insrt(segment s){
    numset.insert(s);
    lenset.insert(s);
    return;
}
void erse(segment &s){
    assert(*numset.find(s)==s);
    assert(*lenset.find(s)==s);
    numset.erase(s),lenset.erase(s);
    return;
}
int sit(int pers){
    segment s=*lenset.begin();//根据距离来选择最近的	
    vector<segment> in;
    int pos=s.get_max();//选择最佳座位坐下
    if(pos>s.l)in.pb(segment(s.l,pos-1));//讨论需要增加的空段
    if(pos<s.r)in.pb(segment(pos+1,s.r));
    erse(s);
    for(int i=0;i<in.size();i++)insrt(in[i]);
    return pos;
}
void leave(int pers){
    vector<segment> out;
    if(pers!=1){
        segment pre=*(--numset.lower_bound(segment(pers,-1)));//找到out_pos的前面一个空段
        if(pre.r==pers-1)out.pb(segment(pre));
    }
    if(pers!=n&&numset.lower_bound(segment(pers,-1))!=numset.end()){
        segment nxt=*(numset.lower_bound(segment(pers,-1)));
        if(nxt.l==pers+1)out.pb(nxt);
    }
    segment ins=segment(0,0);
    if(out.size()==2)ins=segment(out[0].l,out[1].r);//首尾相接
    else if(out.size()==1){
        if(out[0].r==pers-1)ins=segment(out[0].l,pers);//只接左边
        else ins=segment(pers,out[0].r);//只接右边
    }
    else if(out.size()==0)ins=segment(pers,pers);
    for(int i=0;i<out.size();i++)erse(out[i]);
    insrt(ins);
    return;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    freopen("location.in","r",stdin);
    freopen("location.out","w",stdout);
    cin>>n>>m;
    insrt(segment(1,n));//先插进去1个(1,n)的,表明一整段都是空的
    for(int i=1;i<=2*m;i++){
        int a;cin>>a;
        if(seat[a])leave(seat[a]);
        else seat[a]=sit(a);
    }
    for(int i=1;i<=m;i++)cout<<seat[i]<<'\n';
    return 0;
}

D. 跑步路线

难度:绿
最小生成树+lca。
当初死磕t2磕疯了,没看见,眼睛真是瞎了。
注意开int128。

#include<bits/stdc++.h>
#define ll long long
#define mxn 200010
#define pb push_back
#define lit __int128_t
using namespace std;
struct edge{
    ll u,v,w;
    
}e[mxn];
bool operator<(const edge &a,const edge &b){
    return a.w<b.w;
}
struct edge2{
    ll v,w;
    edge2(ll _v,ll _w){
        v=_v,w=_w;
    }
};
int n,m,f[mxn],lg[mxn];
int fa[mxn][30],dep[mxn],fath[mxn];
ll sze[mxn],dis[mxn];
ll k,tim;
lit ans=0;
vector<edge2> t[mxn];
int fnd(int x){
    if(x==f[x])return x;
    return f[x]=fnd(f[x]);
}
void kruskal(){
    sort(e+1,e+m+1);
    int cnt=0;
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v;
        int fu=fnd(u),fv=fnd(v);
        if(fu==fv)continue;
        f[fu]=fv;
        cnt++;
        t[u].pb(edge2(v,e[i].w));
        t[v].pb(edge2(u,e[i].w));
        if(cnt>=n-1)break;
    }
    return;
}
void dfs(int u,int f){
    fa[u][0]=f,dep[u]=dep[f]+1,fath[u]=f;
	for(int i=1;i<=lg[dep[u]];i++)
		fa[u][i]=fa[fa[u][i-1]][i-1];
	for(int i=0;i<t[u].size();i++){
		int v=t[u][i].v;
		if(v==f)continue;
        dis[v]=dis[u]+t[u][i].w;
		dfs(v,u);
	}
    return;
}
int lca(int a,int b)
{
	if(dep[a]<dep[b])
		swap(a,b);
	while(dep[a]>dep[b])
		a=fa[a][lg[dep[a]-dep[b]]-1];
	if(a==b)return a;
	for(int i=lg[dep[a]]-1;i>=0;i--)
		if(fa[a][i]!=fa[b][i])
			a=fa[a][i],b=fa[b][i];
	return fa[a][0];
}
void lcainit(){
    for(int i=1;i<=n;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    dfs(1,0);
    return;
}
void print(lit a){
    if(a>=10)print(a/10);
    putchar(a%10+'0');
    return;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    // freopen("run.in","r",stdin);
    // freopen("run.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>e[i].u>>e[i].v>>e[i].w;
        f[i]=i;
    }
    kruskal();
    lcainit();
    cin>>k>>tim;
    int uu,vv;
    cin>>uu;
    for(int i=1;i<k;i++){
        cin>>vv;
        if(uu==vv)continue;
        int lc=lca(uu,vv);
        ll diss=dis[uu]+dis[vv]-2*dis[lc];
        ll d=dep[uu]+dep[vv]-2*dep[lc];
        ans+=(lit)d*(lit)tim;
        ans+=(lit)diss;
        uu=vv;
    }
    ans-=(lit)tim;
    print(ans);
    return 0;
}

标签:20241003,int,ll,pers,return,segment,模拟,out
From: https://www.cnblogs.com/nagato--yuki/p/18445590

相关文章

  • 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......
  • 10.4 模拟赛(2025 炼石计划 NOIP 模拟赛 #7)
    2025--炼石计划--9月25日--NOIP模拟赛#7【订正】-比赛-梦熊联盟(mna.wang)复盘赢麻了。浏览题。T1没理解“中间节点”是啥意思,样例太大先不模拟了。T2什么东西,密铺?T3好像看懂了题。脑子中瞬间有一个\(n^3\)DP,发现\(n\le200\)感觉切了。但其实DP假的很......
  • KDY-二轮模拟-ZHX补题报告
    1.比赛情况T1三个T2合体T3矩形T4数对总分100pts70pts20pts20pts210pts2.赛中概况第一第二题比较简单,用了1小时搞定。(第一题全体AK)第3,4题难度飙升,想了好久最后改用暴力,共得40分,符合预期。3.题目解析 T1暴力出奇迹1.1问题描述现在科学家在培养 A,B,C三种微生......
  • [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-......
  • 20241003
    公交车(bus)显然的题目,答案就是所有连通块的大小减一之和#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e7+5;intn,m,fa[N],sz[N],ans;intfind(intx){if(fa[x]==x){returnx;}returnfa[x]=find......
  • 20241003校模拟
    A纪念一下本人在校模拟用线段树优化dp单杀*900。最小和最大没有本质区别,这里只讨论最小的情况。设\(f_i\)表示前缀\(i\)的答案,显然是要枚举\(j\)使得\((j,i]\)合并成一段:\[f_i=\min\bigg(f_j+\lceil\dfrac{s_i-s_j}{x}\rceil\bigg)\]其中\(s_i=\sum_{i......
  • 10.3 - AM - 模拟赛 总结
    复盘T1很水,一道异或求和,但是某两位仁兄因没打括号而死。T2很水,一道字符串处理,但是我和某位仁兄因没特判而死(虽然没有hack掉我,所以我理论上还是满分)。T3不水,看了很久,没想出来,自闭了就去看了T4。发现也做不出来。此时我出去晃了一圈,大概是不知道从哪里看到了一个“二”字......