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 \endmatrixp1p_1p2? 、… 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<=2109,然后多试几组数据就会发现NNNSSS同级,所以pi≤Sp_i\leq\sqrtSpi?S

? 于是考虑暴搜,先筛出≤S\leq\sqrtSS

?的所有质数,先枚举 pip_ipi?,对于每个pip_ipi?,枚举aia_iai?暴搜,如果搜到S==1S==1S==1的话,答案+1

特别的,如果S−1S-1S1为质数,且S−1≥S-1\geS1当前要搜的质数,答案也要+1,此时的数为

已搜出的数*(S−1S-1S1

以上是关于icodelab 找朋友(P4397 [JLOI2014]聪明的燕姿)的主要内容,如果未能解决你的问题,请参考以下文章

icodelab 约数序列

bzoj3629 / P4397 [JLOI2014]聪明的燕姿

P4397 [JLOI2014]聪明的燕姿

icodelab 最多的约数

icodelab 等边三角形

如何实现面料数字找朋友?