1. 程式人生 > >NOIP Day1總結

NOIP Day1總結

Day1T1玄學考試

在開始之前,我犯了考前綜合症,各種不安各種焦躁。

結果當我去到考場的時候,看了T1......

T1:road

這不是裸的原題麼這!我當時心裡瞬間想到積木大賽。這明顯就是積木大賽的改裝!只不過積木大賽是向上堆出一座小山,而這個是把路填平。

有啥區別啊這!於是我就把我曾經寫的照搬上去:

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
    int n,ans=0;
    scanf("%d",&n);
    int l=0;
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        if(t>l)
            ans+=t-l;
        l=t;
    }
    printf("%d\n",ans);
    return 0;
}

然後100分就到手了2333。

做完之後我擡頭看了一眼我的隔壁,只看見他寫的其中一行就知道他要爆零了:sort(d+1,d+1+n);

這行會直接徹底讓你的程式只輸出最大坑的深度值,然後就沒有然後了。。。

洛谷上出現了自測,於是賽後我就跑過去自測了一下。你就有了\(\color {green}{AC}\)

T2:money

這題我拿到後是徹底的懵了,這個題目難度簡直像是梯度上升啊!有點小緊張,於是想到學長的話:

“第二、三題你就拿個\(\huge \color {lightblue} {部分的分}\)就好了。”

於是跑去看看部分分,很好,有可以拿的:\(n=2\)

。但是有點小緊張,因為感覺看不懂題目。在重新平穩了一下自己後,我開始想:題目給的\(n\)都是大於2的,我手造資料似乎總是很玄學的看不出規律,那麼.....?

我看了看題目,總算看懂了:\(m\)不會大於\(n\)的,而且不能再在這個陣列以外的數字去選。說明了我們\(n=2\)的時候\(m\)只有兩個選擇:\(m=1,m=2\)

於是開始造資料生成器:

#include<iostream>
using namespace std;
int main()
{
    srand(clock());
    int n=2;
    while(1)
    {
        int a=rand()%20+1;
        int b=rand()%20+1;
        printf("%d\n%d %d\n",n,a,b);
    }
    return 0;
}

使用while(1)是因為這樣我可以無限的製造資料來觀察。

於是觀察了幾組:

第一組:2 7 4,第二組:2 16 14,第三組:2 4 16

突然發現誒,如果a%b==0成立,那麼b就可以取代a成為獨立的貨幣。即\(m=1\)。否則\(m=2\)。然後匆忙寫完。

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
    int n,t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        cin>>n;
        if(n==2)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(a%b==0||b%a==0||(a+b)%a==0||(a+b)%b==0)
                cout<<"1"<<endl;
            else
                cout<<"2"<<endl;
        }
    }
    return 0;
}

然後你就有\(\color {red}{15}\)分的好成績:

T3:track

好吧這題完全超出了我的能力範圍......即使是部分分 \(\small \color {black}{還不是你沒弄懂Floyd}\)

仔細看了看部分分:\(a_i=1\),說明了這個圖會退化成一棵只有根節點的樹:

但是我又注意到了一個:\(m=1\),也就是說:當我們\(a_i=1,m=1\)的時候,為了取最小值最大化,那就是可以直接取所有的道路,全部建成道路,這時候直接輸出所有的道路總長就完事了:

#include<iostream>
#include<stdio.h>
using namespace std;
int w[30010];
int tw;
int n,m;
int main()
{
    bool cheat_a1=true;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        scanf("%d%d%d",&u,&v,&w[i]);
        if(u==1)
            cheat_a1=true;
        tw+=w[i];
    }
    if(cheat_a1&&m==1)
        cout<<tw<<endl;
    return 0;
}

預期是5pts(\(Q\omega Q\)),暫時不知道評測結果,估計會涼掉。

考試的時候當場嘗試\(Floyd\)

void floyd()
{
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                e[i][j]=e[i][k]+e[k][j];
            }
        }
    }
}

然後就爆掉了,當場\(\color {purple}{RE}\)....QAQ

然後看了看之前我到底幹了什麼,當時在想:要跑最大路,可是我似乎不會如何改造\(\color {blue}{Floyd}\)為最大路,於是我轉向另一個思考方向:如果我把所有的權值全部轉換成負數呢?這麼一來就可以跑最小路了(吧)。

於是我加了一句:edge[u][v]=-w[i];(之前開了\(edge[][]\)陣列來玩鄰接矩陣)然後就跑炸了期望是\(\color {red}5\)分,然後洛谷跑出了這個:

wc多了\(\color {red}5\)分!對於我簡直是\(\huge \color {green}{AC}\)

也就是說我今天的分數是:\(\huge \color {green}{125}\)!(本來預計是\(\color {blue}115\)的)

完美