蓝桥杯-数字游戏

问题描述: 给定人的个数n, 取的模值k, 栋栋要报的数字个数T, 求T个数字之和

问题分析: 本题最直接的做法是 模拟这个报数的过程,每两个人之间的差值 在逐渐增加,每次都加一。把每个人要报的数 放在一个sayDigit数组里,这个数组保留n个元素,分别是每轮每个人要报的数,当栋栋报完之后,立即累加到结果中。

代码展示:

#include <iostream>
using namespace std;

int main(){
    int n,k,T;
    cin>>n>>k>>T;
    int sayDigital[n]; //表示n个人说出的数字序列
    long long result = 0;
    //等栋栋报完,立即将报的数累加
    int i = 0;
    int j = 0;
    sayDigital[0] = 1;
    result += sayDigital[0];
    int step = 1;
    do{
        j = i;
        i = (i+1)%n;
        sayDigital[i] = (sayDigital[j] + step)%k;
        step = (step+1)%k;
        if(i==0){
            result += sayDigital[i];
            T--;
        }
    }while(T>1);
    cout<<result<<endl;
    return 0;
}

不幸的是,上述方法只能得到66分,做法没错,只是数据量过大,后两组数据超时了。


方法2:通过观察数据,我得到了下面的规律,假设用num[i]表示栋栋要报的第i个数,则num[1] = 1, 意思是栋栋报的第一个数是1.

当i > 1时,num[i] = (n*(n+1)/2 + n*n*(i-2) + num[i-1])%k 有了这个规律后,我们只要将num数组前T个元素累加即可。

规律解释:上式的推出是找规律得出的。

不管有几个人,他们要报的数是以下序列(先不考虑取模): 1,2,4,7,11,16,22,29,37,46,56,67,79……

那么当n=2时,栋栋要报的数是1,4,11,22,37…… 1和4之间差3,4和11之间差7,11和22之间差11. 由此发现差的值,3,7,11它们之间竟然总是4。  4=2*2=n*n,  而差值初值3不就是2*(2+1)/2=n*(n+1)/2嘛

当n=3,栋栋要报的数是1,7,22,46…… 1和7之间差6,7和22之间差15,22和46之间差24. 由此发现差的值,6,15,22它们之间竟然总是9。  9=3*3=n*n,  而差值初值6不就是3*(3+1)/2=n*(n+1)/2嘛

代码展示:

//AC代码
#include <iostream>
using namespace std;

int main(){
    long long n,k,T;
    cin>>n>>k>>T;
    long long result = 0;
    long long num[1000001];
    num[1] = 1;
    result += num[1];
    for(int i=2;i<=T;i++){
        num[i] = (n*(n+1)/2+n*n*(i-2)+num[i-1])%k;
        result += num[i];
    }
    cout<<result<<endl;
    return 0;
}
这里千万注意,n,k,T 要定义成long long型,以为for循环里面涉及到n*n的计算,在内存中是将n*n的值先赋值给n的,所以要把n的类型定成long long, 不然不能得100分呐,血的教训。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值