icodelab 找朋友(P4397 [JLOI2014]聪明的燕姿)
Posted mysh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了icodelab 找朋友(P4397 [JLOI2014]聪明的燕姿)相关的知识,希望对你有一定的参考价值。
描述
老师给每个同学一个号码牌,假设小明的号码牌上写着数字 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=\beginmatrix \prod_i=1^n \endmatrix\beginmatrix \sum_j=0^a_i p_i^j \endmatrix( p1p_1 、 p2? 、… pn为质数)
因为 S<=2∗109S<=2*10^9,然后多试几组数据就会发现 NN, 、SS同级,所以 pi≤Sp_i\leq\sqrtS
于是考虑暴搜,先筛出 ≤S\leq\sqrtS? 的所有质数,先枚举 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_1p_2^a_2p_3^a_3…p_n^a_nN=p1a1??p2a2??p3a3??…pnan?? 那么约数和
S=∏i=1n∑j=0aipijS=\beginmatrix \prod_i=1^n \endmatrix\beginmatrix \sum_j=0^a_i p_i^j \endmatrixS=∏i=1n??∑j=0ai??pi?j?(p1p_1p1?、p2p_2p2?、…pnp_npn?为质数)
因为S<=2∗109S<=2*10^9S<=2∗109,然后多试几组数据就会发现NNN、SSS同级,所以pi≤Sp_i\leq\sqrtSpi?≤S
? 于是考虑暴搜,先筛出≤S\leq\sqrtS≤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)
以上是关于icodelab 找朋友(P4397 [JLOI2014]聪明的燕姿)的主要内容,如果未能解决你的问题,请参考以下文章