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<