藍橋杯 -- 歷屆試題 數字遊戲【數學題,值得一看】
阿新 • • 發佈:2019-01-08
歷屆試題 數字遊戲
時間限制: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
AC程式碼2:
遊戲的規則是這樣的:棟棟和同學們一共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; 原題連結:
題目給的範圍有點大,如果直接模擬肯定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;
}