1. 程式人生 > >藍橋杯 -- 歷屆試題 數字遊戲【數學題,值得一看】

藍橋杯 -- 歷屆試題 數字遊戲【數學題,值得一看】

歷屆試題 數字遊戲   時間限制:1.0s   記憶體限制:256.0MB 問題描述   棟棟正在和同學們玩一個數字遊戲。

  遊戲的規則是這樣的:棟棟和同學們一共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; 原題連結:
http://lx.lanqiao.cn/problem.page?gpid=T115

題目給的範圍有點大,如果直接模擬肯定TLE,所以得選取特殊方法進行處理。網上看了好多人部落格裡的程式碼都是不能AC的,唯一找到一份能AC的,但是隻有一條TA能看懂的註釋。在眾多的部落格中,終於找到了解決方法,即:通過數學方法直接計算出每次棟棟所報之數,直接計算求和即可得到答案。

題目中所給樣例過於簡單,換做測試資料第一組。

 n=5,k=13,t=41;

第零次棟棟所報數字均為1。

要計算第一次棟棟所報數字,就要先算出其餘人所報數字之和。再加上棟棟第一次所報數字即為要報數字。具體為:

1+(1+2+3+4+5)=16

第二次:16+(6+7+8+9+10)=56

第三次:56+(11+12+13+14+15)=?

第x次:s[x-1]+((x-1)*n+1+x*n)*n/2=?

(x-1)*n+1為後面等差數列的第一個數

(x*n)為後面等差數列的最後一個數

再運用等差數列求和公式即可得到結果。

還要注意一個細節:n,k,l也要定義成LL!

AC程式碼1:

#include <iostream>
using namespace std;
typedef long long LL;
int main()
{
    LL n,k,t;
    while(cin>>n>>k>>t)
    {
        LL ans=1;
        LL last=1;
        LL x;
        for(int i=1; i<t; i++)
        {
            x=last+((i-1)*n+1+i*n)*n/2;
            x%=k;
            ans+=x;
            last=x;
        }
        cout<<ans<<endl;
    }
    return 0;
}

AC程式碼2:
#include <iostream>
using namespace std;
typedef __int64 LL;
int main()
{
    LL n,k,t;
    while(cin>>n>>k>>t)
    {
        LL sum=1;
        LL x=1;
        LL ans=1;
        for(int i=1; i<t; i++)
        {
            sum+=((i-1)*n+1+i*n)*n/2;
            sum%=k;
            //cout<<sum<<" ";
            ans+=sum;
        }
        cout<<ans<<endl;
    }
    return 0;
}