ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOI模拟20

2022-06-08 15:01:15  阅读:117  来源: 互联网

标签:dep ch 20 NOI int mn read -- 模拟


这个是安徽的省选诶,猝不及防的四个题,时间分配能力的一个极大地挑战!!

第一题就是个快速求lcm,可以发现只有根号种长度的环!

第二题好像还挺简单的,特殊性质明示性挺强的

三四题确实是不会了,甚至最后一题写都没有写,其实是一个错误的决定,因为瞎贪心一下就能拿很多分吧!!

T3 山河重整

考场上用的\(n^2\)的dp,因为前面肯定是连续的,新加一个数只会增加右边界!

那么我们可以得到一个性质,出现一个数x不能被表示的时候,他前面选出来的数加和一定是x-1

所以我们正难则反,统计不合法的情况,发现我们其实要找的是一个数划分成几个互不相同的数的方案数

这样的数的个数最多是根号n个,所以我们可以dp去找,其实是个套路,不要一个数一个数的加,我们每次给所有数加1

额,意思就是,我们可以每次添加一个数或者给所有数加一,当然每次必须强行给全局加一

发现这个过程如果正着就这样去做的话,好像非常的困难,所以我们就每次给全局加1,或者删掉一个数

这样相当于做一个完全背包了,当然到这里这个题并没有做完,但是已经基本成型,剩下的我需要容斥来算最终的答案

但是发现可以对当前点造成贡献的点一定是\(\frac{1}{2}\)之前,于是我们递归一半,然后在做上面的过程就行了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=5e5+5;
int n,ans,mod,f[N],g[N];
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
inline int mo(int x){return x>=mod?x-mod:x;}
void sol(int x){
    // cerr<<x<<endl;
    if(x<=1)return ;
    sol(x>>1);
    // cerr<<x<<endl;
    fo(i,0,x)g[i]=0;
    fu(i,x,1)if(i*(i+1)/2<=x){
        fu(j,x,i)g[j]=g[j-i];
        for(int j=0;j+(j+2)*i<=x;j++)g[j+(j+2)*i]=mo(g[j+(j+2)*i]+f[j]);
        fo(j,i,x)g[j]=mo(g[j]+g[j-i]);
    }
    fo(i,(x>>1)+1,x)f[i]=mo(f[i]-g[i]+mod);
}
signed main(){
    freopen("rebuild.in","r",stdin);
    freopen("rebuild.out","w",stdout);
    n=read();mod=read();
    fu(i,n,1)if(i*(i+1)/2<=n){
        // cerr<<i<<endl;
        fu(j,n,i)f[j]=f[j-i];
        f[i]=mo(f[i]+1);
        fo(j,i*2,n)f[j]=mo(f[j]+f[j-i]);
    }f[0]=1;
    // cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
    sol(n);
    // cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
    ans=ksm(2,n);
    fo(i,0,n-1)ans=(ans-f[i]*ksm(2,n-i-1)%mod+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

T4 回忆

这个是个贪心题,发现我们要考虑的只有两个因素

第一个是子树之间的合并,第二个是子树中没有结束的点的向上贡献,于是这个题做完了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=2e5+5;
int T,n,m;
vector<int> e[N];
int dep[N],a[N],b[N],tag[N],mn[N],to[N];
void dfs1(int x,int f){
    dep[x]=dep[f]+1;
    for(int y:e[x])if(y!=f)dfs1(y,x);
}
void dfs2(int x,int f){
    for(int y:e[x])if(y!=f){
        dfs2(y,x);b[y]+=tag[dep[x]];tag[dep[x]]=0;
        if(mn[y]==dep[x])mn[y]=0,b[y]++;
        if(mn[x]&&mn[y]){
            if(mn[x]<mn[y])tag[mn[y]]++;
            else tag[mn[x]]++,mn[x]=mn[y];
        }
        else mn[x]|=mn[y];
        if(b[x]<b[y])swap(b[x],b[y]),swap(a[x],a[y]);
        if(b[y]+2*a[y]>=b[x]){
            int w=b[y]+2*a[y]+b[x];
            a[x]+=(w>>1);b[x]=(w&1);
        }
        else b[x]-=b[y]+2*a[y],a[x]+=b[y]+2*a[y];
    }
    if(to[x]){
        if(!mn[x]){
            mn[x]=to[x];
            if(b[x])b[x]--;
            else if(a[x])a[x]--,b[x]++;
        }
        else mn[x]=min(mn[x],to[x]);
    }
}
void sol(){
    n=read();m=read();
    fo(i,1,n-1){
        int x=read(),y=read();
        e[x].push_back(y);e[y].push_back(x);
    }
    dfs1(1,0);
    fo(i,1,m){
        int x=read(),y=read();
        if(!to[y]||to[y]>dep[x])to[y]=dep[x];
    }
    dfs2(1,0);
    printf("%d\n",a[1]+b[1]);
    fo(i,1,n)e[i].clear(),dep[i]=to[i]=mn[i]=a[i]=b[i]=tag[i]=0;
}
signed main(){
    freopen("memory.in","r",stdin);
    freopen("memory.out","w",stdout);
    T=read();
    while(T--)sol();
}

标签:dep,ch,20,NOI,int,mn,read,--,模拟
来源: https://www.cnblogs.com/hzoi-fengwu/p/16355680.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有