题目
国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续N天每天收到N枚金币后,骑士会在之后的连续N+1天里,每天收到N+1枚金币。
请计算在前K天里,骑士一共获得了多少金币。
输入描述:
输入只有1行,包含一个正整数K,表示发放金币的天数。
示例1:
输入
6
输出
14
说明
骑士第一天收到一枚金币;第二天和第三天,每天收到两枚金币;第四、五、六天,每天收到三枚金币。因此一共收到1+2+2+3+3+3=14枚金币。
示例2:
输入
1000
输出
29820
备注
对于100%的数据,1 ≤ K ≤ 10,000。
题目大意
骑士每连续 i 天每天会得到 i 个金币,(i = 1, 2, 3 , …),那么展开看每一天可以得到的金币数:1 2 2 3 3 3 4 4 4 5 5 5 5 5 …
可以发现就是1个1 ,2个2, 3个3…,那么我们相同的一段分开来看,他们的加和正好就是这段里面相同数字的平方,而每一段里的数字个数就等于这段里的相同数字,那么我们想知道到第k 个数完整加了多少段就可以从1 开始遍历,如果 k = 7 ,那么前面加了完整的三段分别是1, 2 2 , 3 3 3,看成个数就是1 , 2 , 3,那么我们就能想到用数列加和公式 n * ( n + 1) / 2 算出来他的个数,那么剩下的不够下一段的个数直接乘下一段应为的数就好了,比如这个例子就是 7 - 3 * (3 + 1)/ 2 = 1;这个应该是一个 4 ,最后答案就是完整的段 加上剩余的段 = 1 ^ 2 + 2 ^ 2 + 3 ^ 2 + 1 * 4 = 18。
下面展示一些 `详细代码`。
#include<stdio.h>
int main()
{
int k ;// 有k天
scanf("%d",&k);//输入k
int res = 0;//用来记录加到第 i 段时 总个数 >= k
for(int i =1;i <= 200;i ++)
{
if(i*(i + 1) / 2 >= k){
res = i;//记录
break;//已经找到跳出循环
}
}
int m = res - 1;//m 表示第k天之前加了多少个完整的段(就是相邻赐予金币数相同的一段天数)
int cnt = k - m *(m + 1)/ 2;//记录完整的m段之后剩余的天数,最多满足完整的下一段
int ans = 0;//记录总金币
for(int i = 1;i <= m;i ++)//m段逐个加起来
{
ans = ans + (i * i);
}
ans += (m + 1) * cnt;//把剩余的加起来,因为前面已经加了m个完整的段,那么剩余的每一天得到的金币都是m + 1,并且剩余的天数即cnt不可能大于m + 1.
printf("%d" , ans);//输出答案
return 0;
}