NOIP2018模拟9.15总结

版权声明:蒟蒻的东西,随便转载,但要贴个链接 https://blog.csdn.net/an_oi_ing_ymq/article/details/82714455

这里写图片描述
就是这样


分数100+80+60=240
RANK1
暴力真是爽


T1题意
有N个点,M条边,K个特殊点,边权为1
求每个点到离他最远的特殊点的最短距离
NK<=10000000
显然暴力
T1代码

#include<bits/stdc++.h>
#define N 300001
using namespace std;
int i,j,k,l,n,m,tot,tov[N],b[N],a[N],x,y,next[N],last[N],dis[N],dl[N],head,tail;
void lian(int x,int y){tot++,tov[tot]=y,next[tot]=last[x],last[x]=tot;}
void spfa(int x)
{
    memset(dis,126,sizeof dis);
    dis[x]=0,dl[1]=x,head=0,tail=1;
    while(head<tail)
    {
        head++;
        int i=dl[head];
        for(j=last[i];j;j=next[j])
        {
            int y=tov[j];
            if(dis[y]<=m)continue;
            dis[y]=dis[i]+1;
            tail++;
            dl[tail]=y;
        }
    }
    for(int i=1;i<=n;i++)b[i]=max(b[i],dis[i]);
}
int main()
{
    freopen("oasis.in","r",stdin);
    freopen("oasis.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=k;i++)scanf("%d",&a[i]);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        lian(x,y),lian(y,x);
    }
    for(i=1;i<=k;i++)
    {
        spfa(a[i]);
    }
    for(i=1;i<=n;i++)printf("%d ",b[i]);
}

T2题意
有N个点,点的度数为1或2,无重边自环,不要求联通, 求方案数,对998244353取膜
有大样例
练习xjb猜公式的能力
T2代码

#include<bits/stdc++.h>
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define mo 998244353
int n,x,y,z;
long long c[2001][2001],f[2001][2001],jc[3001],sum,a[3001];
using namespace std;
int main()
{
    freopen("map.in","r",stdin);
    freopen("map.out","w",stdout);
    scanf("%d",&n);
    fo(i,1,n){scanf("%d",&z);if(z==1)x++;else y++;}
    if(x%2==1)
    {
        printf("0");
        return 0;
    }
    x/=2;
    fo(i,0,n)c[0][i]=1;
    fo(i,1,n)fo(j,1,n)c[i][j]=(c[i][j-1]+c[i-1][j-1])%mo;
    jc[0]=1;
    fo(i,1,n)jc[i]=(jc[i-1]*i)%mo;  
    if(x==0)
    {
        a[0]=1;
        fo(i,1,y)
        {
            fo(j,3,i)a[i]=(a[i]+a[i-j]*c[j-1][i-1]%mo*c[2][j-1]%mo*jc[j-3]%mo)%mo;
        }
        printf("%lld",a[y]);
        return 0;
    }   
    f[0][0]=1;
    fo(i,1,y)
    {
        fo(j,3,i)f[0][i]=(f[0][i]+f[0][i-j]*c[j-1][i-1]%mo*c[2][j-1]%mo*jc[j-3]%mo)%mo;
    }
    fo(i,1,x)
    {
        f[i][0]=f[i-1][0]*(i*2-1)%mo;
        fo(j,1,y)
        {
            f[i][j]=0;
            fo(k,0,j)f[i][j]=(f[i][j]+f[i-1][j-k]*(2*i-1)%mo*c[k][j]%mo*jc[k]%mo)%mo;
        }
    }
    printf("%lld ",f[x][y]);
}

T3题意
有一个长度为N的序列,权值在0~ 10 9 以内
每次修改一个值,然后求编号最小的权值恰好等于它前面所有点的权值之和的点(好像有点乱)
每次修改一个值,如果一个点的权值等于他前面所有点的权值之和,那它就是“史上最大毒瘤”,找出编号最小的史上最大毒瘤
开O2
练习xjb n 2 50000 的能力

#include<bits/stdc++.h>
using namespace std;
int i,n,m,x,y,j,k,sum,ans,a[50001];
int main()
{
    freopen("challenge.in","r",stdin);
    freopen("challenge.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    ans=2147483647;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        a[x]=y;
        if(ans<x)
        {
            printf("%d\n",ans);
            continue;
        }
        sum=k=0;
        for(j=1;j<=n;j++)
        {
            if(a[j]==sum)
            {
                ans=j;
                printf("%d\n",ans);
                k=1;
                break;
            }
            sum+=a[j];
        }
        if(k==0)
        {
            printf("-1\n");
            ans=2147483647;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/an_oi_ing_ymq/article/details/82714455