2018藍橋杯|歷屆試題|數字游戲


問題描述
  棟棟正在和同學們玩一個數字游戲。
  游戲的規則是這樣的:棟棟和同學們一共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;
我的答案:
#include<iostream>
using namespace std;
int main(){
    int n,k,t;
    cin>>n>>k>>t;
    int figure=1,sum=0;
    for(int i=0;i<t*n;i++){
        figure=(figure+i)%k;
        if(i%n==0){
            sum+=figure;
        }
    }
    cout<<sum;
    return 0;
}

但是運行至第五個測試數據時,顯示運行超時。(而且應該將int型的n,k,i 改為long long型 )
因此,需要找到更優化的算法。

以下兩個程序來自CSDN社區。

第一種:

http://blog.csdn.net/ohpyoo/article/details/44427859

代碼:

#include<stdio.h>
int main(void){
    int i,n,k,t;
    long long sum=1,a=1,cnt=1; 
    scanf("%d%d%d",&n,&k,&t);
    for(i=0;i<t-1;i++){
        cnt=((a+a+n-1)*n/2+cnt)%k;        //下一個數字 
        sum+=cnt;
        a=a+n;        //下一次的起始變量 
    }
    printf("%I64d\n",sum);
    return 0; 
}

思路:我們其實只需要知道東東的數字就好,而對他朋友的數字,我們並不關心,東東的數字從1開始,報出T個數字,那么就是游戲進行了T-1圈,而每次東東報出數字,距他下一次報數中間間隔n次,而報的數字又是每次加1,那么這是一個等差數列,我們可以算出每兩個數之間間隔多少,然后加上上一次報的數對於k求余就是這次得數,然后累加到sum中,但是由於循環次數過大,考慮溢出問題,把有溢出危險的變量聲明的大一點
第二種:

http://blog.csdn.net/qq_30076791/article/details/50578701

代碼:

#include<stdio.h>
int main()
{
    long long n,k,t;
    while(~scanf("%lld%lld%lld",&n,&k,&t))
    {
        long long x=1,ans=1;
        long long l=1,r=n;
        for(int i=1; i<t; i++)
        {
            x+=(l+r)*n/2;
            x=x%k;
            ans+=x;
            l=1+i*n;
            r=n+i*n;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

思路與第一種相同。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM