CF1263C
原题链接https://vjudge.net/contest/350953#problem/I
题意大概为有n个金币交给不知道数目的人来平分,问有多少种情况;
比如5
假如有6个以上的人,显然不可能平分,所以为0;
假如有5个人,一人一个金币 每人为1
假如有4个人,一人一个 多一个不使用 每人为1;
假如有3个人,一人一个;
假如有2个人,一人两个 为2;
假如只有一个人,一个人5个金币;
去重之后可以发现 答案就有四种情况 为0 1 2 5;
如果数据较小我们就可以通过遍历标记来计算,很显然我交的数组太小RE了┭┮﹏┭┮ 但是太大数组装不下的话我们就要思考一下其中的规律(其实我使用的还是很暴力的做法,不过做出来就行了嘛)
PS;
假如现在有10个金币,对于不同的人分情况讨论
人数:每个人的金币;
1:10;
2:5;
3:3;
4:2;
5:2;
6:1;
7:1;
8:1;
9:1;
10:1;
11:0;
我们可以发现当有第一个相同的平分的方法出现的时候,4和5的值2;
2-0的所有值都会出现;这里只举例了一个较小的例子,可以写更大的来观察。所以我们只需要找出有出现相同数字的第一个值即可将之前的数用数组记录,之后的数直接输出,
如例子
将10 5 3 2 记录在数组中,对于剩下的直接输出0-1输出就好
输出可能会有一点乱,不过没关系,按照自己的习惯来就好
假如t是有相同数字的第一个数,我分为3部分
第一部分 0;
第二部分 1到t-1;(0也可以放到这一部分,还有t,也就是0到t);
第三部分 数组中的数字(我将t储存在了数组中,也可以不存,在第二部分输出)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
long long a[300005];
int main()
{
long long t;
scanf("%lld", &t);
while (t--)
{
long long n;
scanf("%lld", &n);
memset(a, 0, sizeof(a));
if (n == 1)//1和2 要特判一下,数字太少,数组存有点问题,就两个直接特判一下。
{
printf("2\n");
printf("0 1\n");
continue;
}
else if (n == 2)
{
printf("3\n");
printf("0 1 2\n");
continue;
}
long long i, z = 1;
a[0] = 0;//第一位为0;
long long t;
long long p = 0;
for (i = 1;; i++)//寻找有相同值的第一个数字
{
t = n / i;
if (t == a[z - 1])//记录
{
p = 1;
break;
}
a[z] = t;
z++;
}
long long ans = z + t - 1;//答案的种数t包含在a数组数组中,所以要减去一个数字,下面输出也是,我将t放在了数组a中储存,所以不是输出0-t而是0-(t-1);
printf("%lld\n", ans);
sort(a, a + z);//对于数组中的数从小到大排序;
printf("0");//第一位为0;
for (i = 1; i < t; i++)//输出1-(t-1);
{
printf(" %lld", i);
}
for (i = 1; i < z; i++)//将数组中的数输出;
{
printf(" %lld", a[i]);
}
cout << endl;
}
return 0;
}