描述
老师给每个同学一个号码牌,假设小明的号码牌上写着数字 S,那么其他那些手上的号码牌数字的所有正约数之和等于 S的同学就是小明的朋友。
输入
输入包含 k 组数据。 对于每组数据,输入包含一个数字S。
输出
对于每组数据,输出有两行,第一行包含一个整数 m,表示有 m 个小明的朋友。
第二行包含相应的 m 个数,表示小明朋友的手中的数字。
注意:你输出的数字必须按照升序排列。
输入样例 1
42
输出样例 1
3 20 26 41
提示
对于 100%的数据,k≤100, S≤2×10^9
思路
对于一个数 NN ,如果它的标准分解式为 N=p1a1p2a2p3a3…pnan 那么约数和
S=∏i=1n∑j=0aipijS=\begin{matrix} \prod_{i=1}^n \end{matrix}\begin{matrix} \sum_{j=0}^{a_i} {p_i}^j \end{matrix}( p1p_1 、 p2? 、… pn为质数)
因为 S<=2∗109S<=2*10^9,然后多试几组数据就会发现 NN, 、SS同级,所以 pi≤S{p_i}\leq\sqrt{S}
于是考虑暴搜,先筛出 ≤S\leq\sqrt{S}
? 的所有质数,先枚举 pi,对于每个 pip_i,枚举 aia_i暴搜,如果搜到S==1 的话,答案++
特别的,如果 S−1S-1为质数,且 S−1≥ 当前要搜的质数,答案也要++,此时的数为
已搜出的数*( S−1S-1)
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1000010; long long q; bool vis[N+5]; int m,flag=0,tot=0; int a[(N+5)<<2],pr[N+5]; bool check(int x) { if(x==1) return 0; if(x<=N) return !vis[x]; for(int i=1; pr[i]*pr[i]<=x; ++i) if(x%pr[i]==0) return 0; return 1; } void dfs(long long now,int x,long long y) { if(now==1) { a[++flag]=y; return; } if(now-1>=pr[x] && check(now-1)) a[++flag]=y*(now-1); int i; long long p,tmp; for(i=x; pr[i]*pr[i]<=now; ++i) { tmp=pr[i]; p=pr[i]+1; for(; p<=now; tmp*=pr[i],p+=tmp) if(now%p==0) dfs(now/p,i+1,y*tmp); } return; } int main() { for(int i=2; i<=N; i++) { if(!vis[i]) pr[++tot]=i; for(int j=1; j<=tot&&i*pr[j]<=N; j++) { vis[i*pr[j]]=1; if(i%pr[j]==0) break; } } while(~scanf("%d",&m)) { q=sqrt(m); memset(a,0,sizeof(a)); flag=0; dfs(1LL*m,1,1LL); printf("%d\n",flag); sort(a+1,a+flag+1); for(int i=1; i<flag; i++) printf("%d ",a[i]); if(flag) printf("%d\n",a[flag]); } return 0; }
对于一个数NNN,如果它的标准分解式为N=p1a1p2a2p3a3…pnanN=p_1^{a_1}p_2^{a_2}p_3^{a_3}…p_n^{a_n}N=p1a1??p2a2??p3a3??…pnan?? 那么约数和
S=∏i=1n∑j=0aipijS=\begin{matrix} \prod_{i=1}^n \end{matrix}\begin{matrix} \sum_{j=0}^{a_i} {p_i}^j \end{matrix}S=∏i=1n??∑j=0ai??pi?j?(p1p_1p1?、p2p_2p2?、…pnp_npn?为质数)
因为S<=2∗109S<=2*10^9S<=2∗109,然后多试几组数据就会发现NNN、SSS同级,所以pi≤S{p_i}\leq\sqrt{S}pi?≤S
? 于是考虑暴搜,先筛出≤S\leq\sqrt{S}≤S
?的所有质数,先枚举 pip_ipi?,对于每个pip_ipi?,枚举aia_iai?暴搜,如果搜到S==1S==1S==1的话,答案+1
特别的,如果S−1S-1S−1为质数,且S−1≥S-1\geS−1≥当前要搜的质数,答案也要+1,此时的数为
已搜出的数*(S−1S-1S−1)
原文地址:https://www.cnblogs.com/mysh/p/11306299.html