线上OJ:
一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid=1969
核心思想:
解法1、由于数据量只有 10000
天,估可以采用 模拟每一天 的方式。
#include <bits/stdc++.h>
using namespace std;
int k = 0;
int main()
{
int ans = 0, coin = 1, cnt = 0;
cin >> k;
for(int i = 1; i <= k; i++) // k 轮
{
ans += coin; // +当前的金币金额
cnt++; // 金币出现的次数+1(比如3出现了1次,出现了2次,出现了3次)
if(cnt == coin) // 如果金币金额和金币出现的次数相等(连续3天出现3),则重置金币数量和金币出现的次数
{
coin++;
cnt = 0;
}
}
cout << ans << endl;
return 0;
}
解法2、在 数据量大 的情况下,模拟每一天容易超时,此时可以考虑用瞪眼法寻找数学规律
比如我们的目标是第6天:在如下的表格中,发现
第6天正好在完整的第3轮
。所以第6天的金币数量前3轮的金币数量总和,1*1+2*2+3*3 = 14
比如我们的目标是第13天:在如下的表格中,发现第13天
正好是走过了完整的4轮
,它自身在第5轮
。所以第13天的金币数量前面完整4轮的金币数量总和,再加上后面还缺的3天,即 (1*1+2*2+3*3+4*4)+5*3 = 31
综上所述,方法二是先找出完整的n轮
,然后每一轮的金币直接用 i*i 计算
(不用for循环i次),再补上最后缺的金币即可。
#include <bits/stdc++.h>
using namespace std;
int k = 0;
int main()
{
int ans = 0, lun = 0; // 第1轮1个,第2轮2个,第3轮3个,第4轮4个。可知6在第3轮,7在第4轮
cin >> k;
while(k >= ++lun) // 如果剩余的轮次还次包含完整的一轮(lun) ,则继续。
k -= lun;
lun--; // 跳出时,最后一次while多了一次++lun,所以要减回去
for(int i = 1; i <= lun; i++)
ans += i * i; // 第i轮的金币数量是 i*i
ans += (lun + 1) * k; // 把最后一轮不完整的金币加上
cout << ans;
return 0;
}