1. 程式人生 > >NOIP2014普及組解題報告 -----by IAMACER

NOIP2014普及組解題報告 -----by IAMACER

本人是濰坊一中的wyw,69級,今年高一,
現在馬上就要NOIP了, 打算把歷年的NOIP普及、提高組題目都做一下, 然後寫寫解題報告∵這個報告主要是給初中同學看的,所以我會寫的詳細一點

NOIP2014普及組解題報告

Prolem 1 珠心算測試(count)

這道題其實很簡單, 意思就是說給你一些數a1,a2,a3,a4...an
然後讓你回答有多少個A+B=C(A ≠ B ≠ C)滿足(回答C的數量,而不是等式的數量)

方法一

那麼有一種很明顯的做法就是三層迴圈列舉C、A、B,
注意:C是在最外層,若找到了一個A和一個B,滿足上述等式,則C是一個符合要求的解,這時ans++,並且退出當前列舉,列舉下一個C,這種演算法的時間複雜度是O

(N3)

而我當時沒想到這個演算法,因為有更好用而且簡單更不容易出錯的解法,

方法二

i=1...n,j=i+1...nai+ajyou[ai+aj]truea1anyou[ai]ans++

這個演算法的好處在於它很好寫,不用退出什麼的,也不用注意迴圈的順序,而且時間複雜度是O(N2)

程式碼(方法2):

#include<cstdio>

using namespace std;

int n, a[101], i, j, count;
bool you[20001]={false};

int
main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); for(i=1;i<n;i++) for(j=i+1;j<=n;j++) you[ a[i]+a[j] ]=true; count=0; for(i=1;i<=n;i++) count += you[ a[i] ]; printf
("%d\n",count); return 0; }

在此徵求一下大神的意見,如有更快的做法,敬請奉上

小結:

這道題很簡單,但很多人沒有做對的原因就是沒有好好理解題意,但是根本原因其實還在於心態太驕傲了,認為是第一題就可以輕視,這樣是不好的,水題我們更要做好啊,你想想同樣是100分,這100分多麼好拿,所以是水題、越該放平心態,細心地做。當時我正是由於重視(2013年第一題爆零的教訓),用了整整15分鐘才做好,最後得了100分

Problem 2 比例簡化

這道題目是說,給定A和B,求解一組A’和B’,滿足以下條件:

ABAB0
0<A,BL
AB互質

首先,想一個總體的框架:
我們發現L100,因此可以列舉AB,然後判斷是否A’B’滿足上述條件,並且打擂臺求比值最小的一組就行了,打擂臺的複雜度是O(1)。設驗證的複雜度為O(k),則總的演算法的複雜度為O(kL2) ,其中L2104,所以我們只要保證k的大小在100以內就一定沒有問題。
現在要求兩個分數的差值,該怎麼辦呢?高精除!很多人一下就想到了,當時我在賽場上就是這麼想的,但是又仔細一考慮。。。。。首先,高精除有風險,而且如果我是出題者的話,我一定會卡高精除,第二,高精除的程式設計複雜度很高,很容易出錯而且耗時間
於是我重新讀題,找尋一些特殊的切入點,終於看到了這個東西:1A,B106,我的腦袋裡瞬間就萌生出一種想法:模擬手動比較分數——就是說如果你要比較兩個分數,就先把他們通分,然後比較分子的大小,如abcd比較,先把它們化成adbdbcbd的形式,然後比較ad和bc的大小,而在整個列舉的過程中,你最大的情況只需要比較ABAB,而且他們分母的乘積最大是108,到此,問題就完美地解決了!

貼上程式碼:

#include<cstdio>
#include<iostream>

using namespace std;

long A,B,a,b,L,besta,bestb;
long long cha_zi, cha_mu, best_cha_zi, best_cha_mu=-1, t1, t2;

void Minus(long long z1, long long m1, long long z2, long long m2, long long &cz, long long &cm)
{   
    z1=z1*m2;
    z2=z2*m1;
    m1=m2=m1*m2;
    cm=m1;
    cz=z1-z2;
}

bool huzhi(int x, int y)
{
    int max, i;
    if(x>y)max=x;
    else max=y;

    for(i=2; i*i<=max; i++)
    {
        if(x%i==0 && y%i==0)
            return false;
    }
    return true;
}

int main()
{
    freopen("ratio.in","r",stdin);
    freopen("ratio.out","w",stdout);

    cin >> A >> B >> L;

    for(a=1;a<=L;a++)
    {
        for(b=1;b<=L;b++)
        {
            if( huzhi(a,b)==true)
            {
                Minus(a,b,A,B,cha_zi,cha_mu);
                if(cha_zi>=0)
                {
                    Minus(best_cha_zi,best_cha_mu,cha_zi,cha_mu,t1,t2);
                    if(t1>0 || best_cha_mu==-1)
                    {
                        best_cha_zi=cha_zi;
                        best_cha_mu=cha_mu;
                        besta=a;
                        bestb=b;
                    }
                }
            }
        }
    }

    cout << besta << " " << bestb << endl;
    return 0;
}

這段程式碼是我初中時寫的,有不足之處還請見諒。。

小結

此道題放在第二個挺合適,特點是程式碼好寫,但方法不是特別好想(與歷年相比),只要按部就班一步一步地來,這道題還是很容易的,我的分數是100分

Problem 3 螺旋矩陣

當我看到這道題的時候,有一種很熟悉的感覺。。。。然後我就想:NOIP怎麼會考這麼簡單的題目?然後。。。。就用了模擬的方法,調了很長時間,但是結果很慘,爆零了(因為直接開了30000*30000的陣列),到現在我也不明白當時為什麼那麼傻。。。。
好了迴歸正題,這道題是有技巧的
觀察這個矩陣
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
想想我們模擬的時候是1 2 3 4,然後轉彎5 6 7,然後轉彎8, 9, 10以此類推,其實我們走了很多不必要的路,比如從1到4,我們可以直接加3,然而怎樣知道應該加上幾呢?試一試:
1+3=4
4+3=7
7+3=10
10+2=12
12+1=13
13+1=14
14+1=15
15+1=16
16+0=0
咦?有規律!
對於每個“圈”,比如說從1到12,這裡面的規律是可以找到的,從1開始,依次加3、3、3、2,而從一個圈到下一個圈的時候,橫座標要+1,然後是+1、+1、+1、+0,規律很容易看出,從這個“圈”的左上角開始,依次加k、k、k、k-1(要搞明白橫縱座標),然而k就是上一個“圈”的k-2得到的,到此問題就解決了
程式碼:

#include<cstdio>
#include<iostream>
using namespace std;
int n,I,J,i,j,k,t,clk;
long x;
int main()
{
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    scanf("%d%d%d",&n,&I,&J);
    x=0;
    i=1;
    j=0;
    for(k=0;k<n/2+n%2;k++)
    {
        if(i!=I)
        {
            j=j+(n-2*k);
            x=x+(n-2*k);
        }
        else
        {
            x=x+(J-j);
            break;
        }
        if(j!=J)
        {
            i=i+(n-2*k-1);
            x=x+(n-2*k-1);
        } 
        else
        {
            x=x+(I-i);
            break;
        }
        if(i!=I)
        {
            j=j-(n-2*k-1);
            x=x+(n-2*k-1);
        }
        else
        {
            x=x+(j-J);
            break;
        }
        if(j!=J)
        {
            i=i-(n-2*k-2);
            x=x+(n-2*k-2);
        }
        else
        {
            x=x+(i-I);
            break;
        }
    }
    return 0;
}

小結

說白了,這道題還是在模擬,只不過換了種方式來模擬,加入了一些小小的優化,我覺得這道題的坑度等級還是很高的,它讓人看了有種很想當然的感覺,會情不自禁地認為:“這道題我會”,結果很多人都爆零了,真是慘痛的教訓啊!
另外,從這道題中我學會了一種方法,那就是像這種數字大規模出現的題目應該手動寫寫,找找規律,這樣有助於解決問題

Problem 4 子矩陣

這道題要好好說說

給出如下定義:
子矩陣:從一個矩陣當中選取某些行和某些列交叉位置所組成的新矩陣(保持行與列的相對順序)被稱為原矩陣的一個子矩陣。
例如,下面左圖中選取第 2、4 行和第 2、4、5 列交叉位置的元素得到一個 2*3 的子矩陣如右圖所示。
相鄰的元素:矩陣中的某個元素與其上下左右四個元素(如果存在的話)是相鄰的。
矩陣的分值:矩陣中每一對相鄰元素之差的絕對值之和。
本題任務:給定一個 n 行 m 列的正整數矩陣,請你從這個矩陣中選出一個 r 行 c 列的 子矩陣,使得這個子矩陣的分值最小,並輸出這個分值。
子矩陣
對於 50%的資料,1 ≤ n ≤ 12, 1 ≤ m ≤ 12, 矩陣中的每個元素 1 ≤ a[i][j] ≤20;
對於 100%的資料,1 ≤ n ≤ 16, 1 ≤ m ≤ 16, 矩陣中的每個元素 1 ≤ a[i][j] ≤1000,1 ≤ r ≤ n, 1 ≤ c ≤ m

這道題乍一眼看來就是爆搜,然而爆搜要列舉行和列,列舉的次數最大約是

相關推薦

NOIP2014普及解題報告 -----by IAMACER

本人是濰坊一中的wyw,69級,今年高一, 現在馬上就要NOIP了, 打算把歷年的NOIP普及、提高組題目都做一下, 然後寫寫解題報告∵這個報告主要是給初中同學看的,所以我會寫的詳細一點 NOIP2014普及組解題報告 Prolem 1 珠心算測

NOIP2000普及解題報告

opened close clas tdi char using div || src /霧 noip2000發生了什麽?為什麽洛谷上就一道題- - 計算器的改良 分析:字符串模擬題。記錄分別記錄等式兩邊的系數與常數即可。以前在codevs上做過,也就直接把代碼貼上來了。

NOIP1999普及解題報告

分析 eat 報告 nlogn cnblogs clas () fun turn 不知怎麽地,洛谷的noip1999普及組的題和以前考的不一樣 /霧 回文數 分析:一道高精度加法的模擬題,註意還有16進制。 #include<iostream> #inclu

NOIP2002普及解題報告

ostream 答案 class ret opened none fin nbsp b- 過河卒 分析:簡單遞推題。註意答案要longlong #include<iostream> #include<algorithm> using namesp

NOIP 2018 普及 解題報告

今年的題目出的有點詭異,難度跨越有點大 入門  to 普及- to(注意:前方東非大裂谷,請小心慢行) 提高+/省選- to 提高+/省選- 不過實際上沒有這麼難 T3、T4 一個DP 一個暴力(雖然不是正解) 也就可以過了 扯入正題 T1 標題統計 這道題十分的水,

NOIP2018普及解題報告

解題報告 洛谷 5015 標題統計 程式碼(題目過水) 洛谷 5016 龍虎鬥 分析 程式碼 洛谷 5017 擺渡車 分析(線性dp) 程式碼(線性dp) 分析(斜率

NOIP 2010 普及解題報告

NOIP 2010普及組解題報告 北京市八一中學 王祺磊 感謝: 我也學習一下,現在的流行趨勢,先開始感謝,但這真的是發自內心的感覺,讓我發出一下這些感謝。 一、感謝和我一起並肩戰鬥資訊學奧賽教學一線的老師們,是你們給了我溫暖,讓我感受到一個溫馨的集體,在其中,我們一起學習,一起研討

noip2013普及解題報告

第一題:記數問題 題目描述 Description 試計算在區間1到n的所有整數中,數字x(0≤x≤9)共出現了多少次?例如,在1到11中,即在1、2、3、4、5、6、7、8、9、10、11中,數字1出現了4次。 輸入描述 Input Descriptio

NOIP2017普及 解題報告

前言 好吧,由於賽時本人還是一個蒟蒻,(雖然現在也是),導致一直沒有做完後面兩題。。。 先說下賽時分數吧。。。 前兩題日常水過,後兩題日常放棄,其實第三題有想著做但是沒時間了 第一題 第二題 第三題 第四題 Accepte

紀中訓練 day5 【NOIP普及】模擬賽D 解題報告

目錄 大意 從左到右,問加了一個’p’後一共有幾個noi?(p可以為n,o,i中的一個)長度小於100001 思路 加p之前,noi的個數為每個o之前n的個數*之後i的個數並累加。 加p之後,有三種情況:N,O,I N肯定是放在

珠心算測驗(NOIP2014 普及第一題)

變化 空格 不同 too 提示 通過 clas syntax 輸出 描述 珠心算是一種通過在腦中模擬算盤變化來完成快速運算的一種計算技術。珠心算訓練, 既能夠開發智力,又能夠為日常生活帶來很多便利,因而在很多學校得到普及。 某學校的珠心算老師采用一種快速考察珠心算加法能力的

子矩陣(NOIP2014 普及第四題)

定義 clas 輸出格式 syntax 一個 begin 包含 amp cdn 描述 給出如下定義: 子矩陣:從一個矩陣當中選取某些行和某些列交叉位置所組成的新矩陣(保持行與 列的相對順序)被稱為原矩陣的一個子矩陣。 例如,下面左圖中選取第 2、4 行和第 2、4、5 列

題解:子矩陣(NOIP2014普及T4)

+= out bsp tdi 又是 style 預處理 sizeof 表示 又是dp 暴力枚舉會T 考慮先固定一個變量,比如先枚舉行 然後預處理每行之間的絕對值,每列之間的絕對值 然後dp進行轉移 註意記錄選擇的行數 轉移記得加上新選的列的行之間的絕對值,即w[

2015-9-13 NOIP模擬賽解題報告(by hzwer)

++ ron 解題報告 正整數 max 決策 pty uri 由於 小奇挖礦 「題目背景」 小奇要開采一些礦物,它駕駛著一臺帶有鉆頭(初始能力值w)的飛船,按既定路線依次飛過喵星系的n個星球。 「問題描述」 星球分為2類:資源型和維修型。 1.資源型:含礦物質量a[i],若

[jzoj]2018.08.09【NOIP提高】模擬賽C:解題報告

目錄: 1.種類分配(Breed Assignment) 2.資訊傳遞(Message Relay) 3.計算周長(Perimeter) 4.找奶牛(Find the Cow!) 1.種類分配(Breed Assignment) 題目:

2018年12月29日普級 解題報告

首先看第一題,比較明顯的模擬題,打了高精度,第二題暫時沒思路,先剛第三題,先想到dfsdfsdfs求層數,發現可以直接用並查集搞搞,就過了,第四題沒思路,就碼了第四題,發現可以直接用桶排,過掉。第四題仔

2018年11月30日普級 解題報告

首先第一題是個很明顯的水題切掉了,第二題發現都是1,於是就輸出了1,竟然有50!第三題打了貪心40,總分190 T1 婚禮上的小杉 排序題,略掉吧。。。 話說我是本題唯一一個O(n)O(n)O(n)過的 T2 玩詐欺的小杉 給定變化規則,求最終矩陣 這是經典

NOIP2017提高解題報告

D1: T1:這題考場推1個半小時結論也不知道打表找規律。我還是太菜了。NOIP有史以來的最短程式碼如下: #include<bits/stdc++.h> using namespace std; long long a,b; int mai

Noip2018普及初賽試題解題報告

解題思路: 一、單項選擇題 (答案:DDDBBAAAABABBBB) 1、除D外,其餘均為輸入裝置。 2、除D外,其餘都等於(617)10 ,D選項為(619)10。 3、1MB=1024KB=1024*1024B 4、廣域網,即WideAreaNetwork,縮寫WAN。 5、百度百科:198

NOIp2018普及初賽解題報告

題目:NOIp2018普及組初賽試卷 先附上答案: 今年的題目有點詭異,我們來看看怎麼做! 一、選擇題 D。第一題水題,印表機肯定是輸出裝置嘍。 D。第二題涉及到了進位制轉換,我們可以都轉換為十進位制,或只算末位數。發現D末位是9,其他都是7。 D。這是常識:1GB=1024KB