列表

详情


NC20140. [JLOI2014]聪明的燕姿

描述

阴天傍晚车窗外
未来有一个人在等待
向左向右向前看
爱要拐几个弯才来
我遇见谁会有怎样的对白
我等的人他在多远的未来
我听见风来自地铁和人海
我排着队拿着爱的号码牌
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字S,那么自己等的人手上的号码牌数字的所有正约数之和必定等于S。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。

输入描述

输入包含k组数据(k ≤ 100)
对于每组数据,输入包含一个号码牌S

输出描述

对于每组数据,输出有两行,第一行包含一个整数m,表示有m个等的人,
第二行包含相应的m个数,表示所有等的人的号码牌。
注意:你输出的号码牌必须按照升序排列。

示例1

输入:

42

输出:

3
20 26 41

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 79ms, 内存消耗: 2936K, 提交时间: 2021-02-14 10:12:27

#include<bits/stdc++.h>
using namespace std;
const int N=100000;
int st[N],prime[N],cnt;
int ans[N];
int len;
bool isprime(int n)
{
	if(n<N)
	return !st[n];
	for(int i=0;prime[i]<=n/prime[i];i++)
	{
		if(n%prime[i]==0)
		return false;
	}
	return true;
 } 
 void getprime(int n)
 {
 	for(int i=2;i<=n;i++)
 	{
 		if(!st[i])
 		prime[cnt++]=i;
 		for(int j=0;prime[j]<=n/i;j++)
		 {
		 	st[i*prime[j]]=1;
		 	if(i%prime[j]==0)
		 	break;
		  } 
	 }
 }
 void dfs(int last,int prod,int s)
 {
 	if(s==1)
 	{
 		ans[len++]=prod;
 		return;
	 }
	 if(s-1>(last<0?1:prime[last])&&isprime(s-1))
	 ans[len++]=prod*(s-1);
	 for(int i=last+1;prime[i]<=s/prime[i];i++)
	 {
	 	int p=prime[i];
	 	for(int j=p+1,t=p;j<=s;t*=p,j+=t)
	 	if(s%j==0)
	 	dfs(i,prod*t,s/j);
	 }
 }
 int main()
 {
 	int s;
 	getprime(N-1);//重点 
 	while(cin>>s)
 	{
 		len=0;
 		dfs(-1,1,s);
 		cout<<len<<endl;
 		if(len)
 		{
 			sort(ans,ans+len);
 			for(int i=0;i<len;i++)
 			printf("%d ",ans[i]);
 			printf("\n");
		 }
	 }
	 return 0;
 }

上一题