1296. 聪明的燕姿


题目链接

1296. 聪明的燕姿

求所有数字的所有正约数之和等于 \(S\) 的数。

输入格式

输入包含 \(k\) 组数据。

对于每组数据,输入 \(S\)

输出格式

对于每组数据,输出有两行。

第一行包含一个整数 \(m\),表示有 m 个数。

第二行包含相应的 \(m\) 个数。

注意:你输出的数必须按照升序排列。

数据范围

\(1≤k≤100,\)
\(1≤S≤2×10^9\)

输入样例:

42

输出样例:

3
20 26 41

解题思路

筛质数,dfs

一个数 \(x=p_1^{c_1}\times p_2^{c_2}\times \dots \times p_n^{c_n}\),其正约数之和为 \((1+p_1+p_1^2+\dots+p_1^{c_1})\times (1+p_2+p_2^2+\dots+p_2^{c_2})\times \dots \times (1+p_n+p_n^2+\dots+p_n^{c_n})\)

即需要找出满足这样形式的正约数之和为 \(s\) 的数有多少个,不妨考虑dfs\(p_n\)\(c_n\),这样的复杂度太高,需要剪枝:首先 \(c_n,特判掉当前 \(1+p_n=s\) 的情况,即 \(s-1\) 为质数且比前一个质数要大,防止重复,这样后面必须满足 \(p_n\times p_n\leq s\)

  • 时间复杂度:\(O(k\sqrt{s}logs)\)

代码

// Problem: 聪明的燕姿
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1298/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include 
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair PII;
 
template  bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template  bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template  void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5;
int m,s,prime[N],v[N];
vector res;
void primes(int n)
{
	memset(v,0,sizeof v);
	for(int i=2;i<=n;i++)
	{
		if(v[i]==0)
			v[i]=prime[++m]=i;
		for(int j=1;j<=m;j++)
		{
			if(prime[j]>n/i||v[i](last<=0?1:prime[last]))res.pb(num*(now-1));
	for(int i=last+1;prime[i]<=now/prime[i];i++)
	{
		int p=prime[i];
		for(int j=p,t=1+p;t<=now;j*=p,t+=j)
			if(now%t==0)dfs(i,now/t,num*j);
	}
}
int main()
{
    primes(N-1);
    while(cin>>s)
    {
    	res.clear();
    	dfs(0,s,1);
    	sort(res.begin(),res.end());
    	cout<