1. 程式人生 > >Loi_20181029_互測

Loi_20181029_互測

T1 鹹魚計數 || CF185A Plant

連結

A 鹹魚計數 (count.cpp) 【題目描述】 傳說很久很久以前,世界上只有一條鹹魚。 世界上所有的鹹魚都是它的後代。 當這條鹹魚出現的時候,它是這樣的 而這一年被鹹魚們記錄下來,稱為鹹魚紀元的開始。 一年之後,它分裂了。然後變成了這個樣子。 又過了一年,每條分裂的小鹹魚也再次分裂,變成了下面這個樣子。現在請你算一算,過了 n 年之後,有多少條頭朝上的鹹魚。 【輸入描述】 一行一個整數 n。 【輸出描述】 一個整數,表示頭朝上的鹹魚數量。這個數可能很大,我們只需要它對 1000000007 取模的結果。 【樣例輸入 1】 1 【樣例輸出 1】 3 【樣例輸入 2】 2 【樣例輸出 2】 10 【資料範圍及提示】 50%的資料,n <= 1e6 100%的資料,n <= 1e18

拿到題,1018。看出複雜度是O(1)或者O (log2(n))。 開始找規律, 在第0年時,有1條魚, 在第1年時,有3條魚, 在第2年時,有10條魚, 在第3年時,有36條魚。 好像找不出規律,在畫個圖試試。

。。。

畫的不好請見諒… 發現了什麼…每行的黃色(也就是向上的),都是它上一行+1。 那麼第n年一共有幾行?我們發現第n年的行數,是n-1年行數的兩倍。那麼到第n年,就有 2n 行。 那就可以做了,就是算出sum(1+2+3+4+…+ 2n )。 誒,好像不大對。這個複雜度好像是 O( 2n ),顯然過不了。

那還有什麼辦法? (聽別人說可以用等差數列…然而我才初中,並不會) 還記得小學裡,老師讓算從1加到100嗎? 還記得那個高斯,他把 1+99 , 2+98 , 3+97 這樣,一個一個加起來的嗎? 那我們也這樣,手玩一下,找到公式: sum(1+2+3+4+…+ r (r是偶數) ) = (r/2 -1)*r+r/2+r 此處的r就是行數, r=2n

。 把式子化簡一下,得到:sum(1+2+3+4+…+2 n ) =2(2*n-1) + 2(n-1) 這個東西就可以O(log2(n))的用快速冪來求了。 這是程式碼。

#include<iostream>
#include<cstdio>
using namespace std;
#define p 1000000007
#define LL long long

LL inp()
{
    LL Ans;char c;bool o=false;
    while((c=getchar())<'0'||c>'9')if(c=='-')o=true;Ans=c-48;
while((c=getchar())>='0'&&c<='9')Ans=(Ans<<3)+(Ans<<1)+c-48; return o==true?-Ans:Ans; } LL n,r,rr; LL ksm(LL a,LL b) { LL ans=1; while(b) { if(b&1)ans=(ans*a)%p; b>>=1; a=(a*a)%p; } return ans; } int main() { n=inp(); if(n==0){cout<<1;return 0;} if(n==1){cout<<3;return 0;} if(n==2){cout<<10;return 0;} LL ans=(ksm(2,2*n-1)+ksm(2,n-1))%p; cout<<ans<<endl; }

考試時,看到這個題後很快就有的思路。 打完之後,腦跑資料都對,可一到大樣例就不對,後來又換dp做法,矩陣優化,暴力,就是過不了大樣例,心態直接炸了。再加上後面三個題都沒有思路,直接放棄…當時覺得,我的思路都沒錯啊,就是不對。 結果考完試,才發現,我誤以為1年時有1條魚,所有的n都應該是n-1。到luogu一交0->100。 煩死了啊… 未完待續