2023年多校联训NOIP层测试2

2023年多校联训NOIP层测试2

爆零了

T1 HDU 4786 Fibonacci Tree \(0pts\)

@wangyunbiao: 不可以,总司令

我:不,可以,总司令

@wangyunbiao: 我 \(T1\) 爆零了

我: 我 \(T1\) 也爆零了


  • 赛场上初读题面,以为是毒瘤数据结构(被题面背景祸害),然后直接就跳了(祭)。
  • 易知,令在题目中所给的图的最大生成树的边权之和为 \(maxx\) ,最小生成树的边权之和为 \(minn\) ,那么在 \(minn\) ~ \(maxx\) 之间存在一个数是斐波那契数,则存在一种构造方式使得构造出一棵斐波那契树(因为原图的边权只有 \(0\)\(1\))。
  • 预处理 \(Fibonacci\) ,再跑最小生成树和最大生成树即可(我跑的是 \(Kruskal\) )。
  • 本题常数有点大,请使用 \(scanf,printf\) 或关闭 \(cin,cout\) 同步流 。
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define sort stable_sort 
    #define endl '\n'
    struct node
    {
        int u,v,w;
    }e[300000];
    int f1[300000],f2[300000],fib[300000],vis[300000],cnt,minn,maxx;
    void add(int u,int v,int w)
    {
        cnt++;
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
    }
    bool cmp(node a,node b)
    {
        return a.w<b.w;
    }
    int find(int x,int f[])
    {
        if(f[x]==x)
        {
            return f[x]; 
        }
        else
        {
            return f[x]=find(f[x],f);
        }
    }
    void kruskal(int n)
    {
        int numin=0,numax=0,i,j,x,y;
        sort(e+1,e+cnt+1,cmp);
        for(i=1,j=cnt;i<=cnt,j>=1;i++,j--)
        {
            x=find(e[i].u,f1);
            y=find(e[i].v,f1);
            if(x!=y)
            {
                f1[x]=y;
                minn+=e[i].w;
                numin++;//最小生成树
                if(numin>=n)
                {
                    minn=0;
                    return;
                }
            }
            x=find(e[j].u,f2);
            y=find(e[j].v,f2);
            if(x!=y)
            {
                f2[x]=y;
                maxx+=e[j].w;
                numax++;//最大生成树
                if(numax>=n)
                {
                    maxx=0;
                    return;
                }
            }
        }
        if(numin!=n-1) 
        {
            minn=0;
        }
        if(numax!=n-1) 
        {
            maxx=0;
        }
    }
    int main()
    {
        int t,n,m,u,v,w,i,j,flag;
        scanf("%d",&t);
        fib[1]=fib[2]=1;
        vis[1]=1;
        for(i=3;fib[i-1]<=100010;i++)
        {
            fib[i]=fib[i-1]+fib[i-2];
            vis[fib[i]]=1;
        }
        for(i=1;i<=t;i++)
        {
            scanf("%d%d",&n,&m);
            cnt=minn=maxx=flag=0;
            for(j=1;j<=n;j++)
            {
                f1[j]=f2[j]=j;
            }
            for(j=1;j<=m;j++)
            {
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);
                add(v,u,w);
            }
            kruskal(n);
            if(minn!=0&&maxx!=0)
            {
                for(j=minn;j<=maxx;j++)
                {
                    if(vis[j]==1)
                    {
                        //printf("Case #%d: ",i);
                        //printf("Yes\n");
                        printf("YES\n");
                        flag=1;
                        break;
                    }
                }
                if(flag==0)
                {
                    //printf("Case #%d: ",i);
                    //printf("No\n");
                    printf("NO\n");
                }
            }
            else
            {
                //printf("Case #%d: ",i);
                //printf("No\n");
                printf("NO\n");
            }
        }
        return 0;
    }
    
  • 貌似改输出格式后 \(HDU\)\(WA\) 了,有知道原因的@我。

T2 期末考试 \(0pts\)

  • 题面中没有明确表明必定有解,但测试数据表明必定有解。
  • 部分分(赛场上没骗到,祭):
    • \(n\) 份答案对应分数都为 \(0\) ( \(10\)pts ):
      • \(n\) 份答案中第 \(i\) 位共出现了 \(sum[i]\) 种字符,则有:$$ans=\prod\limits_{i=1}^{10}(4-sum[i])$$
    • \(n\) 份答案对应分数都为 \(90\) ( \(10\)pts ):
      • \(n\) 份答案共中有 \(x\) 份本质不同,则有:

        \[ans = \left \{ \begin{aligned} &10×C_1^3=10×\frac{3!}{{2}!×1!}=10×3=30 && (x = 1) \\ &C_2^1=\frac{2!}{{1}!×1!}=2 && (x = 2,且两份代码仅有1处答案不同) \\ &1+1=2 && (x = 2,且两份代码仅有2处答案不同,但必定有解) \\ &1 && \text{(otherwise)} \end{aligned} \right. \]

  • 直接爆搜,貌似数据有点差,放过去了 \(O(n×4^n)\)
    • \(ans[]\) 临时存储一个答案,检验这个答案的正确性。如果符合题意,则答案总数 \(++\)
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define sort stable_sort
    #define endl '\n'
    char s[30000][10],ans[10];//慎用string,不开O2可能会祭
    int a[30000],maxx;
    void dfs(int x,int n)
    {
        int i,j,num;
        if(x==10)//检验临时答案是否正确
        {
            for(i=1;i<=n;i++)
            {
                num=0;
                for(j=0;j<=9;j++)
                {
                    if(ans[j]==s[i][j])
                    {
                        num+=10;
                    }
                }
                if(num!=a[i])//说明答案不合法
                {
                    return;
                }
            }
            maxx++;
        }
        else
        {
            for(i=1;i<=4;i++)//爆搜临时答案
            {
                ans[x]='A'+i-1;
                dfs(x+1,n);
            }
        }
    }
    int main()
    {
        int t,n,i,j;
        cin>>t;
        for(i=1;i<=t;i++)
        {
            cin>>n;
            maxx=0;
            for(j=1;j<=n;j++)
            {
                cin>>s[j]>>a[j];
            }
            dfs(0,n);
            cout<<maxx<<endl;
        }
        return 0;
    }
    
  • 正解貌似是 \(meet \ in \ the \ middle\) ,但没听懂,暂时咕了。

T3 麻烦的工作 \(0pts\)

@wangyunbiao: 不可以,总司令

我:不,可以,总司令

@wangyunbiao: 我 \(T3\) 爆零了

我: 我 \(T3\) 也爆零了

  • 没听懂讲评,暂时咕了。
  • 可参考wkh的。

T4 小X的Galgame \(0pts\)

  • 部分分( \(20pts\) ):输出所有边权之和。
  • 没听懂讲评,暂时咕了。
posted @ 2023-08-02 15:21  hzoi_Shadow  阅读(110)  评论(2编辑  收藏  举报
扩大
缩小