江西财经大学第二届程序设计竞赛同步赛----D-绕圈游戏

首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/635/D
来源:牛客网
设计:等差数列


题目如下:
在这里插入图片描述
在这里插入图片描述
当时被暴力蒙蔽了双眼,没想到只要在excel找一下规律就可以了

先解释一下题目意思:
这里有一个环,环上面写着1->n的数,ddd从1开始每次走k步,直到第二次走到了结束(如果ddd在某次走k步时跨过了1,则还要继续走一圈),ddd每次的落脚点都有一个数,叫你升序输出k从1到n所以情况下,ddd从开始走到结束落脚点数字的和(卧槽,k好大,一个个遍历绝对超时

首先我们可以得到一个结论,ddd落脚点的数字绝对不会大于n,而且结束之前不可能在同一个位置落脚两次。

我们假设这不是一个环,那么ddd所走的路线一定是一个等差数列a[n],但是现在ddd走的是一个环,也就是说,每次ddd落脚点的真实值其实是a[i] mod n,所有的值构成一个数列b[n](b[i]=a[i] mod n),既然a[n]是等差数列,那么b[n]又是一个怎样的数列?

根据以下表格(n=10):
在这里插入图片描述
和下列这个表格(n=6):
在这里插入图片描述
可以不完全归纳出一个事实,即:

每个b数列经过排序后得到的是一个首项为1,末项为n+1,公差为n的因数的数列(项数为n/k+1,k为n的因数)


那么可以把n的所有因数放在一个数组里得到一个公差数组,然后再通过公差数组得到每个公差得到对应的等差数列前n项和,得到的前n项和还要减去数列最后的n+1这个数,所有的前n项和升序输出即为答案!

至于如何得到n的所有因数,可以先把n开方,得到sqrt(n),再从1遍历到sqrt(n),只要n%i==0,那么i和n/i就是n的因数!

不过我用的是链表,方便增删,还有unique函数和sort函数可以用!

前n项的的公式减去 ( n + 1 ) (n+1) (n+1)应该是:
( n + 2 ) ∗ ( n / k + 1 ) / 2 − n − 1 (n+2)*(n/k+1)/2-n-1 (n+2)(n/k+1)/2n1

ps:数据类型很大,要用long long类型!!!


代码如下:

#include <iostream>
#include <list>
#define f(i) (ll)(n+2)*(n/i+1)/2-n-1//通过公差i得到前n项和减去(n+1)的值
using namespace std;
typedef long long ll;
int n;
list<ll> list1;//链表用来存所有的前n项和(减去n+1)
int main(){
	cin>>n;
	int i,j=1;
	for(i=1;i*i<=n;i++)
		if(n%i==0){//i为n因数的条件
			list1.push_back(f(i));
			list1.push_back(f((n/i)));//放入链表
		}	
	list1.unique();list1.sort();
	//unique函数用来删除重复的值,sort函数用来排序
	while(list1.size()!=0){//输出
		cout<<list1.front()<<" ";
		list1.pop_front();
	}
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值