2019年8月8日(NOIP模拟赛DAY2)

NOIP18年好难T_T~~~

prob1:旅行

60分的部分分肯定都会做,现在就是看剩下的40分怎么转成那60分的情况。

那40分情况是\(n=m\),很明显是一个基环树,根据题目性质,肯定有一条边没跑,那么就枚举边,一条条删,再用60分的方法跑,得到答案。

时间复杂度\(O(n^2)\):

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define jinitaimei signed
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=5e3+10;
vector <int> e[xx];
bool vis[xx],viss[xx],to[xx];
int n,m,pre[xx],delx,dely,u[xx],v[xx],ans[xx],tmp[xx],all=0;
inline void dfs1(int g)
{
    vis[g]=true;
    printf("%d ",g);
    int tp;
    do
    {
        tp=6e3;
        fur(i,0,(int)e[g].size()-1)
        {
            if(vis[e[g][i]]) continue;
            tp=min(tp,e[g][i]);
        }
        if(tp<6e3) dfs1(tp);
    }while(tp<6e3);
}
inline void dfs2(int g)
{
    vis[g]=true;
    tmp[++all]=g;
    fur(i,0,(int)e[g].size()-1)
    {
        if(vis[e[g][i]]) continue;
        if(e[g][i]==delx&&g==dely) continue;
        if(e[g][i]==dely&&g==delx) continue;
        dfs2(e[g][i]);
    }
}
jinitaimei main()
{
    n=in;m=in;
    fur(i,1,m)
    {
        u[i]=in,v[i]=in;
        e[u[i]].push_back(v[i]);
        e[v[i]].push_back(u[i]);
    }
    if(n-1==m) dfs1(1);
    else
    {
        if(n==5000) m=m*2/3;
        fur(i,1,n) sort(e[i].begin(),e[i].end()),ans[i]=6e3;
        fur(i,1,m)
        {
            delx=u[i];
            dely=v[i];
            all=0;
            fur(j,1,n) vis[j]=false;
            dfs2(1);
            bool change=false;
            if(all<n) continue;
            fur(j,1,n)
            {
                if(ans[j]!=tmp[j])
                {
                    change=ans[j]>tmp[j];
                    break;
                }
            }
            if(change&&all==n) fur(j,1,n) ans[j]=tmp[j];
        }
        fur(j,1,n) printf("%d ",ans[j]);
    }
    printf("\n");
    return 0;
}  

prob2:填数游戏

考场上懵逼的我只推出了\(n=1&n=2\)的规律。

首先要明确两个性质:\(1.\)矩阵中每条对角线(本文对角线均默认为从左下到右上的对角线)上的数都是单调不增的。\(2.\)当有两个点对\((x,y-1)\)\((x-1,y)\)上填的数相同时,以\((x,y)\)为左上端点,\((m,n)\)为右下端点的矩阵中的每条对角线上的数都是相同的。

这两个性质的满足是使矩阵合法的充要条件。

有性质推出结论(大力模拟):\(1.\)\(Ans(n,m)=Ans(m,n)\),由此可以使\(n\)总不大于\(m\),故下文中的\(n\)恒不大于\(m\)\(2.\)\(Ans(n=1,2,3,m)\)的通项公式;\(3.\)\(n=m\)\(n+1=m\)\(Ans(n,m)\)的通项公式;\(4.\)\(n>=4\land m>=n+1\)\(Ans(n,m+1)=3* Ans(n,m)\)

就一暴力模拟\(+\)数学,但相当之恶心。

T_T……

式子太恶心了……

#include<bits/stdc++.h>
using namespace std;
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define int long long
const int mod=1e9+7;
inline int power(int x,int k){int res=1;for(;k;x=x*x%mod,k>>=1) if(k&1) res=res*x%mod;return res;}
signed main()
{
    int n,m;
    cin>>n>>m;
    if(n>m) swap(n,m);
    if(n==1) cout<<power(2,m)<<endl;
    if(n==2) cout<<4*power(3,m-1)%mod<<endl;
    if(n==3) cout<<112*power(3,m-3)%mod<<endl;
    if(n<=3) return 0;
    if(n==m) cout<<(83*power(8,n)%mod+5*power(2,n+7)%mod)%mod*power(384,mod-2)%mod<<endl;
    else cout<<(83*power(8,n)%mod+power(2,n+8))%mod*power(3,m-n-1)%mod*power(128,mod-2)%mod<<endl;
    return 0;
}

prob3:保卫王国

先贴\(O(nm)\)的暴力吧:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define int long long
#define jinitaimei signed
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=1e6+10,inf=1e10;
int f[xx][2],c[xx],a,x,b,y;
vector<int>e[xx];
bool flag;
inline void dfs(int j,int fa)
{
    if(flag) return;
    if(j!=a&&j!=b) f[j][0]=0,f[j][1]=c[j];
    else if(j==a) f[j][x^1]=inf,f[j][x]=x==1?c[j]:0;
    else if(j==b) f[j][y^1]=inf,f[j][y]=y==1?c[j]:0;
    fur(i,0,(int)e[j].size()-1)
    {
        if(e[j][i]==fa) continue;
        dfs(e[j][i],j);
        if(flag) return;
        if(f[j][0]!=inf) f[j][0]+=f[e[j][i]][1];
        if(f[j][1]!=inf) f[j][1]+=min(f[e[j][i]][1],f[e[j][i]][0]);
        if(f[j][1]==inf&&f[e[j][i]][1]==inf)
        {
            flag=true;
            return;
        }
    }
}
jinitaimei main()
{
    int n=in,m=in;
    char op[3];scanf("%s",op);
    fur(i,1,n) c[i]=in;
    fur(i,1,n-1)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    fur(i,1,m)
    {
        a=in,x=in,b=in,y=in;
        flag=false;
        dfs(1,0);
        if(flag||f[1][0]>=inf&&f[1][1]>=inf) puts("-1");
        else printf("%lld\n",min(f[1][1],f[1][0]));
    }
    return 0;
}

转载于:https://www.cnblogs.com/ALANALLEN21LOVE28/p/11330522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NOI(全国青少信息学奥林匹克竞模拟的测试数据是指用于评测参选手的程序的输入和对应的输出。测试数据是非常重要的,因为它决定了参选手的程序能否正确地解决问题。 在NOI模拟中,测试数据具有以下特点: 1.充分覆盖:测试数据应涵盖各种可能的输入情况,包括边界条件和极端情况。通过提供不同的测试数据,可以考察选手对问题的全面理解和解决能力。 2.随机性和均衡性:为了公平起见,测试数据应该是随机生成的,而不是针对某个特定算法或解法设计的。同时,测试数据应该是均衡的,即各种情况的概率应该大致相等,以避免偏向某些解法。 3.合理性和可行性:测试数据应该是合理和可行的,即符合题目要求的输入数据,并且是选手能够通过编写程序来处理的。测试数据应该考虑到程序的限制和时间复杂度,以充分测试选手的编程能力。 NOI模拟的测试数据通常由经验丰富的考题组负责生成。他们会根据题目的要求和限制,设计出一组合理、充分、随机和均衡的测试数据,以确保参选手的程序在各种情况下都能正确运行,并且能通过性能测试。 总之,测试数据在NOI模拟中起到了至关重要的作用,它既考察了选手对问题的理解和解决能力,又提高了选手编程的技巧和效率。同时,合理和恰当的测试数据也是公平竞的保证,确保每个参选手有相同的机会和条件进行竞争。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值