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
#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。 煩死了啊… 未完待續