2024初三年前集训测试3

2024初三年前集训测试3

T1 夕景昨日 90pts

  • 部分分

    • 10pts :输出 No
    • 20ptsO(2n)DFS 暴力枚举能得到的所有数,用 map 里进行判断。
    • 90pts :输出 Yes
  • 正解

    • 观察到 1n100000,0ai500000
    • 猜测 n 到达一定数量级时,一定有解。
    • n 个数最多产生 2n 个数, ai 最多配对出 nV 个数。经打表,枚举 V=1500000 解关于 n 的不等式 2nV2n ,解得当 V=500000 时,n 的最小整数解为 25
      • 严格意义上来说,极限数据应该造成 1,2,4,8,16,32,
    • 故当 n25 时,仍选择用 DFS 暴力枚举;否则,一定有解。
    点击查看代码
    ll a[100001],flag=0;
    map<ll,ll>vis;
    void dfs(ll x,ll now,ll n)
    {
        if(x==n)
        {
            vis[now]++;
            if(vis[now]==2)
            {
                flag=1;
            }
        }
        else
        {
            dfs(x+1,now+a[x+1],n);
            dfs(x+1,now-a[x+1],n);
        }
    }
    int main()
    {
        ll n,i;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        if(n<=25)
        {
            dfs(0,0,n);
            if(flag==0)
            {
                cout<<"No"<<endl;
            }
            else
            {
                cout<<"Yes"<<endl;
            }
        }
        else
        {
            cout<<"Yes"<<endl;
        }
        return 0;
    }
    

T2 透明答案 70pts

  • 部分分
    • 30pts :输出 Bob
    • 70pts :输出 Ayano
  • 正解
    • 博弈论
      • 弱化

        • 删去“此外,每 3 回合他们会添加一堆石子(含 2 块石子)。换句话说,在第 t 次操作(两个人操作的总次数)之后,如果可以被 3 整除,则添加一堆 2 块石子的石子堆。(即使在第 t 次操作中取完了所有石子,如果 t 可被 3 整除,也会添加新石子堆并继续游戏。)”,其他部分不变。
        • NIM 博弈,有 Ayano 获胜当且仅当 i=1nai=0 时,即 n0(mod2) ;否则,有 Bob 获胜。
      • 手动模拟

        • n=1 时,有 Ayano 获胜。
        • n=2 时,有 Bob 获胜。
        • n=3 时,有 Ayano 获胜。
      • 推广

        • n 拆成 n=n3×3+nmod3 。前面 n3×3 堆答案不造成影响,对答案造成影响的只有 nmod3 。故当 n2(mod3) 时,有 Bob 获胜。 否则,有 Ayano 获胜。
        点击查看代码
        int main()
        {
            int n;
            cin>>n;
            if(n%3==2)
            {
                cout<<"Bob"<<endl;
            }
            else
            {
                cout<<"Ayano"<<endl;
            }
            return 0;
        }
        
    • DFS
      • 出题人称因是普及难度的比赛,所以把 DFS 放过去了。

T3 界外科学 50pts

  • 部分分

    • 50pts :超大背包 O(2n) 枚举。

      点击查看代码
      ll a[50],b[50],ans=0;
      void dfs(ll x,ll worth,ll now,ll n,ll m)
      {
          if(x==n)
          {
              ans=(worth<=m)?max(ans,now):ans;           
          }
          else
          {
              dfs(x+1,worth^a[x+1],now+b[x+1],n,m);
              dfs(x+1,worth,now,n,m);
          }
      }
      int main()
      {
          ll n,m,i;
          cin>>n>>m;
          for(i=1;i<=n;i++)
          {
              cin>>a[i];
          }
          for(i=1;i<=n;i++)
          {
              cin>>b[i];
          }
          dfs(0,0,0,n,m);
          cout<<ans<<endl;
          return 0;
      }
      
    • 100pts

      • 输出 i=1nbi

      • 超大背包 O(2n) 的玄学优化,优化后时间复杂度未知。

        点击查看代码
        ll a[50],b[50],sum[50],ans=0;
        void dfs(ll x,ll worth,ll now,ll n,ll m)
        {
            if(x==n)
            {
                ans=(worth<=m)?max(ans,now):ans;           
            }
            else
            {
                if(now+sum[n]-sum[x]>ans)
                {
                    dfs(x+1,worth^a[x+1],now+b[x+1],n,m);
                }
                if(now+sum[n]-sum[x+1]>ans)
                {
                    dfs(x+1,worth,now,n,m);
                }
            }
        }
        int main()
        {
            ll n,m,i;
            cin>>n>>m;
            for(i=1;i<=n;i++)
            {
                cin>>a[i];
            }
            for(i=1;i<=n;i++)
            {
                cin>>b[i];
                sum[i]=sum[i-1]+(b[i]>0)*b[i];
            }
            dfs(0,0,0,n,m);
            cout<<ans<<endl;
            return 0;
        }
        
      • 面向数据点分治,当 n 较大时,选择 nV01 背包做法。

        • 这里背包不能滚成一维。
  • 正解

    点击查看官方题解

T4 回忆补时 30pts

  • 部分分

    • 30ptsO(n2q) 暴力枚举。

      点击查看代码
      ll k[100001],b[100001];
      int main()
      {
          ll n,q,x,ans,i,j,h;
          scanf("%lld",&n);
          for(i=1;i<=n;i++)
          {
              scanf("%lld%lld",&k[i],&b[i]);
          }
          scanf("%lld",&q);
          for(i=1;i<=q;i++)
          {
              scanf("%lld",&x);
              ans=0;
              for(j=1;j<=n;j++)
              {
                  for(h=j+1;h<=n;h++)
                  {
                      ans=max(ans,max(k[h]*(k[j]*x+b[j])+b[h],k[j]*(k[h]*x+b[h])+b[j]));
                  }
              }
              printf("%lld\n",ans);
          }
          return 0;
      }
      
    • 60pts :当 kj0 时,kix+bi 越大对答案的贡献越大;当 kj<0 时,kix+bi 越小对答案的贡献越小。考虑计算出 kix+bi 的最大值、次大值、最小值、次小值,然后进行转移。

      点击查看代码
      ll k[100001],b[100001];
      int main()
      {
      	ll n,q,x,ans,zmax,cmax,zmin,cmin,idzmax,idzmin,i,j;
      	cin>>n;
      	for(i=1;i<=n;i++)
      	{
      		cin>>k[i]>>b[i];
      	}
      	cin>>q;
      	for(i=1;i<=q;i++)
      	{
      		cin>>x;
      		ans=zmax=cmax=idzmax=idzmin=0;
      		zmin=cmin=0x7f7f7f7f;
      		for(j=1;j<=n;j++)
      		{
      			if(k[j]*x+b[j]>zmax)
      			{
      				cmax=zmax;
      				zmax=k[j]*x+b[j];
      				idzmax=j;
      			}
      			else
      			{
      				cmax=max(cmax,k[j]*x+b[j]);
      			}
      			if(k[j]*x+b[j]<zmin)
      			{
      				cmin=zmin;
      				zmin=k[j]*x+b[j];
      				idzmin=j;
      			}
      			else
      			{
      				cmin=min(cmin,k[j]*x+b[j]);
      			}
      		}
      		for(j=1;j<=n;j++)
      		{
      			if(k[j]>=0)
      			{
      				ans=max(ans,(j==idzmax)?cmax*k[j]+b[j]:zmax*k[j]+b[j]);
      			}
      			else
      			{
      				ans=max(ans,(j==idzmin)?cmin*k[j]+b[j]:zmin*k[j]+b[j]);
      			}
      		}
      		cout<<ans<<endl;
      	}
      	return 0;
      }
      
  • 正解

    点击查看官方题解

总结

  • 打到 8:40 就去打矩阵快速幂了。
  • 要学会通过值域猜测时间复杂度和判断答案范围。

后记

  • 普及模拟赛考博弈论、折半搜索、李超线段树,难评。
  • 没有大样例,差评。
  • 建议本场比赛改名为暴力骗分/良心送分模拟赛。
posted @   hzoi_Shadow  阅读(56)  评论(5编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
扩大
缩小
点击右上角即可分享
微信分享提示