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<s\),特判掉当前 \(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 <bits/stdc++.h>
//#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<int, int> PII;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> 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<int> 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]<prime[j])break;
v[i*prime[j]]=prime[j];
}
}
}
bool is_prime(int x)
{
for(int i=2;i<=x/i;i++)
if(x%i==0)return false;
return true;
}
void dfs(int last,int now,int num)
{
if(now==1)
{
res.pb(num);
return ;
}
if(is_prime(now-1)&&(now-1)>(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<<res.size()<<'\n';
if(!res.size())
continue;
for(int i:res)cout<<i<<' ';
puts("");
}
return 0;
}