今天作了幾道藍橋杯的去年題

   找了幾道簡單的熱熱身,感受本身算法仍是記不住,能描述,不會寫,應該是練少了的緣故。算法

今天一道題交了好幾遍纔對啊,明明是很簡單的題啊啊啊啊啊,算了,先回憶一下心路歷程。ide

題目是這樣的學習

問題描述
  棟棟正在和同窗們玩一個數字遊戲。

  遊戲的規則是這樣的:棟棟和同窗們一共n我的圍坐在一圈。棟棟首先說出數字1。接下來,坐在棟棟左手邊的同窗要說下一個數字2。再下面的一個同窗要從上一個同窗說的數字往下數兩個數說出來,也就是說4。下一個同窗要往下數三個數,說7。依次類推。

  爲了使數字不至於太大,棟棟和同窗們約定,當在心中數到 k-1 時,下一個數字從0開始數。例如,當k=13時,棟棟和同窗們報出的前幾個數依次爲:
  1, 2, 4, 7, 11, 3, 9, 3, 11, 7。

  遊戲進行了一下子,棟棟想知道,到目前爲止,他全部說出的數字的總和是多少。
輸入格式
  輸入的第一行包含三個整數 n,k,T,其中 n 和 k 的意義如上面所述,T 表示到目前爲止棟棟一共說出的數字個數。
輸出格式
  輸出一行,包含一個整數,表示棟棟說出全部數的和。
樣例輸入
3 13 3
樣例輸出
17
樣例說明
  棟棟說出的數依次爲1, 7, 9,和爲17。
數據規模和約定
  1 < n,k,T < 1,000,000;測試

題目就是這樣。因爲T什麼的仍是很大的,把這些數據都保存下來不現實,固然一個優秀的ACMer也根本不會用都保存下來的爛辦法(雖然我連ACMer都不是)。若是不保存數據,很容易就能想到必需要依靠規律,(我怎麼感受我會作的只有找規律的,不開心)網站

規律很容易就想出來了,根據題目描述,那個數列(1,2,4,7,11)在全部狀況下都是固定的,只不過每種狀況被模的數不一樣,以及被棟棟輪到的數不一樣。很容易有遞推公式:f(n) = f(n-1)+n-1;(這裏的n是下標,不是題目中的人數)那麼哪一個位置是棟棟該說的呢?容易知 i % n == 1的那個位置是棟的。由此我寫出了下面的代碼。spa

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int  n,k,T;
 6     int  i = 1,x = 1,x0 = 1;
 7     int  sum = 1;
 8     cin >> n>>k>>T;
 9     for(i=2;i <= (T - 1)*n+1;i++)
10     {
11         x = x +i - 1;
12         if(x > k)x = x%k;
13         if(i % n == 1)sum += x;
14     }
15     cout<<sum<<endl;
16     
17     return 0;
18 }
代碼一

結局顯而易見,超時。T與n很大的時候(甚至不太大的時候)由於for循環裏面是T*n,超時是必然的。code

當時我圖省事,上網學習了一下。有人和我有同樣的問題,而且有一我的回答他,只關注棟棟的數據便可,沒必要每一個數據都要求出來。(番外:回答這個問題的是我同窗啊,我在問問題的時候別人已經開始回答問題了啊!!別問我怎麼知道的,誰叫他全部社交網站都用的是同一張本身的照片呢。)blog

既然只關注棟棟的數據,遞推公式就要從新推理了。以題目中3 13 3的數據分析。易知 f(n) = f(n - 3) + 3n - 6;這裏的n就是下標的意思,爲了不誤會換成 f(a) = f(a - 3) + 3a - 6;題目中是三我的一循環,若是是n我的一循環呢?遞推公式更具通常性。可是,這時,好死不死,我把遞推公式改爲了 f(a) = f(a - n) + 3a - 6;這顯然是不對的,3a - 6也是要改的啊姑娘。當時我沒想到,興沖沖的就改好交了。3a - 6是啥呢,是a - 1 + a - 2 + a - 3;擴展到n是a - 1 + a - 2 + a - 3 +...+a - n;也就是a*n + n(n + 1)/2;遞推公式是f(a) = f(a - n) + a*n + n(n + 1)/2; T是棟報數的次數,用 i 來循環(1,2,3...T)a與i的關係是a = i * n + 1;稍改程序便可。遊戲

不過,個人程序仍是不對,無非就是這兩句程序x0 = x0 + (i * n + 1)* n - n*(n + 1)/2; x = x0%k; sum += x;這個看似正確,其實在對x0取模之後還要再賦值給x0,以便下次使用。由於 sum %d = (a%d +b%d)%d !=(a+b)%d,必定要根據題目中的規定來。改了以後仍是不對,我頹了,感受心累,然而,此時我靈光一現,把數據都改成longlong類型,而後就正確了!!!代碼以下,代碼中大量的註釋記錄了個人思考過程,一點也不捨得刪掉。ci

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     long long  n,k,T;
 6     long long  i = 1,x = 1,x0 = 1;
 7     long long  sum = 1;
 8     scanf("%I64d%I64d%I64d",&n,&k,&T);
 9     /*for(i=2;i <= (T - 1)*n+1;i++)
10     {
11         x = x +i - 1;
12         if(x > k)x = x%k;
13         if(i % n == 1)sum += x;
14     }
15     cout<<sum<<endl;*/
16     for(i = 1;i < T;i++)
17     {
18         x0 = x0 + (i * n + 1)* n - n*(n + 1)/2;
19         //cout<<x0<<endl;
20         x = x0%k;
21         x0 = x;
22         sum += x;
23     }
24      printf("%I64d\n",sum);
25     return 0;
26 }
代碼二

我在網上還看到了一個代碼,遞推公式和我並不同,可是提交也對了。題目中只有6個測試數據,也許並不能真正檢測。網上代碼以下:

 1 #include<stdio.h>
 2 int main()
 3 {
 4     long long n,k,t,i,total=1,op=1,cishu=1;
 5     scanf("%I64d%I64d%I64d",&n,&k,&t);
 6     for(i=1;i<t;i++)
 7     {  long long op1=((n*i+1+n*(i-1))*n/2)%k;
 8         op+=op1;
 9         op%=k;
10         total+=op;
11     }
12     printf("%I64d\n",total);
13     return 0;
14 }
代碼三
相關文章
相關標籤/搜索