2017.11.04【NOIP提高组】模拟赛B组

来源:互联网 发布:epub制作软件安卓版 编辑:程序博客网 时间:2024/06/06 17:38

这次比赛我应该是100分的,但是只有20,就因为堆的down操作打错了。。。gg。
T1:【NOIP2017提高A组冲刺11.2】字典序
最水的一题了,而且也是唯一会做的一题。
就是拓扑排序,再用一个堆优化一下。就好了。

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;int last[100010],next[100010],tov[100010];int n,m,tot;int f[100010];int ans[100010];int num[100010];void insert(int x,int y){    tov[++tot]=y;    next[tot]=last[x];    last[x]=tot;    }void up(int x){    while((x>>1)>0&&f[x]<f[x>>1])    {        swap(f[x],f[x>>1]);        x=x>>1;    }}void down(int x){    int k;    while(((x<<1)<=tot&&f[x]>f[x<<1])||((x<<1)+1<=tot&&f[x]>f[(x<<1)+1]))    {        k=x<<1;        if(k+1<=tot&&f[k+1]<f[k])++k;        swap(f[x],f[k]);        x=k;    }}int main(){    freopen("dictionary.in","r",stdin);    freopen("dictionary.out","w",stdout);    scanf("%d%d",&n,&m);    int i,x,y,j;    for (i=1;i<=m;++i)    {        scanf("%d%d",&x,&y);        insert(x,y);        ++num[y];    }    tot=0;    for (i=1;i<=n;++i)        if(num[i]==0)         {            f[++tot]=i;            up(tot);        }    while(tot)    {        x=f[1];        ans[++ans[0]]=x;f[1]=f[tot--];down(1);        i=last[x];        while(i)        {            y=tov[i];            --num[y];            if(!num[y])            {                f[++tot]=y;                up(tot);            }            i=next[i];        }    }    if (ans[0]<n) printf("-1");    else    for (i=1;i<=ans[0];++i) printf("%d ",ans[i]);    printf("\n");}

T2:【NOIP2017提高A组冲刺11.2】救赎
先用树形dp做出每一个节点为根的期望值。
然后可以递归每个点为根时的期望。这样它的父亲节点就会成为它的儿子。
然后推一推就对了。

#include<cstdio>#include<iostream>using namespace std;long long f[100010];int last[200010],next[200010],tov[200010];long long size[100010],son[100010];long long n,sum,tot,p=998244353;long long ans[100010];void insert(int x,int y){    tov[++tot]=y;    next[tot]=last[x];    last[x]=tot;    }long long ksm(long long x,long long y){    long long k=1,z=x;    while (y>0)    {        if (y&1==1) k=(k*z)%p;        y=y/2;        z=(z*z)%p;    }    return k;}long long moon(long long x,long long y){return ((x-1)*((y-1)*ksm(y,p-2)%p))%p;}void dfs(long long x,int father){    size[x]=1;    for (long long i=last[x];i;i=next[i])    {        if(tov[i]!=father)        {            dfs(tov[i],x);            size[x]+=size[tov[i]];            son[x]++;        }    }    f[x]=moon(size[x],son[x])%p;    sum=(sum+f[x])%p;}void dfs_ans(long long x,long long sf,long long sa,long long father){    long long son_now,son_next;    if(x==1) son_now=son[x];    else son_now=son[x]+1;    ans[x]=(sum-sf-f[x]+moon(n,son_now)%p+sa+p*2)%p;    for (long long i=last[x];i;i=next[i])    {        if(tov[i]!=father)        {            if(x==1) son_next=son[x]-1;            else son_next=son[x];            dfs_ans(tov[i],(sf+f[x])%p,(sa+moon(n-size[tov[i]],son_next))%p,x);         }    }}int main(){    freopen("redemption.in","r",stdin);    freopen("redemption.out","w",stdout);    scanf("%lld",&n);    long long i,x,y;    for (i=1;i<=n-1;++i)    {        scanf("%lld%lld",&x,&y);        insert(x,y);        insert(y,x);    }    dfs(1,0);    dfs_ans(1,0,0,0);    for (i=1;i<=n;++i)        printf("%lld\n",ans[i]);}

T3: 【NOIP2017提高A组冲刺11.2】失格
这题我改的最久。
我们可以发现这是一道最小生成树,然后就会发现不能暴力连边,我们可以只连刚好大于这个点的每个倍数的点。
然后最小生成树的排序部分用筒排。
就过了,细节注意。

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;struct cdy{int x,y,z;};struct cdy2{int x,y;};int n,tot;cdy2 p[100010],p1[100010];int ans,len;int a[100010];int f[100010];cdy edge[32000001];int num[10000001];int q[32000001],q1[32000001];int sum[10000001],chen[10000001];bool cmp2(cdy2 a,cdy2 b){return a.x<b.x;}int find(int x){    if(f[x]==x)return x;    f[x]=find(f[x]);    return f[x];}int main(){    freopen("autosadism.in","r",stdin);    freopen("autosadism.out","w",stdout);    scanf("%d",&n);    int i,j,ma=0;    tot=0;    for (i=1;i<=n;++i)    {        scanf("%d",&p[i].x);        ma=max(ma,p[i].x);        p[i].y=i;    }    sort(p+1,p+1+n,cmp2);    for (i=1;i<=n;++i)    {        if(p[i].x==p[i-1].x)        {            edge[++tot].x=p[i].y;            edge[tot].y=p[i-1].y;            edge[tot].z=0;        }        else        {            p1[++len].x=p[i].x;            p1[len].y=p[i].y;        }    }    int s,l,r,mid,x;    l=2;    for (i=1;i<=ma;++i)    {        if(i<=p1[l-1].x) chen[i]=l-1;        else         {            chen[i]=l;            ++l;        }    }    for (i=1;i<=len-1;++i)    {        edge[++tot].x=p1[i].y;        edge[tot].y=p1[i+1].y;        edge[tot].z=p1[i+1].x%p1[i].x;        x=i+1;        for (j=2;j<=ma/p1[i].x;++j)        {            s=j*p1[i].x;            if(chen[s]!=x)            {                l=chen[s];                edge[++tot].x=p1[i].y;                edge[tot].y=p1[l].y;                edge[tot].z=p1[l].x%p1[i].x;                    x=l;            }        }    }    ma=0;    for (i=1;i<=tot;++i)    {        ++num[edge[i].z];        ma=max(ma,edge[i].z);    }    for (i=0;i<=ma;++i)        sum[i]=sum[i-1]+num[i];    for (i=1;i<=tot;++i)    {        q[++q[0]]=sum[edge[i].z];        q1[q[q[0]]]=i;        --sum[edge[i].z];    }    for (i=1;i<=n;++i) f[i]=i;    int xx,yy,ans,k;    ans=k=0;    for (i=1;i<=q[0];++i)    {        xx=find(edge[q1[i]].x);        yy=find(edge[q1[i]].y);        if(xx!=yy)        {            ++k;            f[xx]=yy;            ans+=edge[q1[i]].z;        }        if(k==n-1)break;    }    printf("%d\n",ans);}
原创粉丝点击