找伙伴

找伙伴(数论 (starstar ))

  • 时限:(1s) 内存:(256M)

Descrption

  • 在班级里,每个人都想找学习伙伴。伙伴不能随便找,都是老师固定好的,老师给出要求:伙伴要凭自己实力去找。
  • 老师给每个人发一张纸,上面有数字。假设你的数字是 (w),那么如果某位同学手中的数字的所有正约数之和等于 (w),那么这位同学就是你的小伙伴。

Input

  • 输入包含n组数据(最多 (100) 组)
  • 对于每组测试数据,输入只有一个数字 (w)

Output

  • 对于每组数据输出两行,第一行包含一个整数 (m),表示有 (m)(如果 (m=0),只输出一行 (0) 即可)个伙伴。
  • 第二行包含相应的 (m) 个数,表示伙伴的数字。注意:小伙伴的数字必须按照升序排列。

Sample Input

42

Sample Output

3
20 26 41

Hint

  • (100\%) 的数据,有 (w<=2*10^9)
  • 来源:(luogup4397)

分析

  • 前两天才做了个约数和定理的题,今天再出个,检验检验大家的掌握情况。

  • 在学习下几个定理:

    1. (N)的标准分解式:

      [N=prod_{i=1}^{k} p_i^{a_i}=p_1^{a_1}*p_2^{a_2}*...*p_n^{a_n} ]

      • (p_1<p_2<...<p_n) 为质数,(a_1,a_2,...,a_n) 为指数,均为正整数。
    2. 对于上面的分解式,(N) 的约数个数为:((a_1+1)*(a_2+1)*...*(a_n+1))

    3. 约数和定理:对上面的分解式,(N) 的约数和为:

      • (f(N)=(p_1^0+p_1^1+...+p_1^{a_1})*(p_2^0+p_2^1+..+p_2^{a_2}*...*(p_n^0+p_n^1+..+p_n^{a_n})))
  • 此题给我们 (N) ,要我们求满足 (N==f(x))(x)

  • 显然 (x=prod_{i=1}^k p_i^{a_i})(N=(p_1^0+p_1^1+...+p_1^{a_1})*(p_2^0+p_2^1+..+p_2^{a_2}*...*(p_n^0+p_n^1+..+p_n^{a_n}))) ,现在我们知道 (N),所以我们可以枚举质数 (p_i) 和其指数 (a_i) 然后对(N) 进行不停拆分,拆分完一个质数就求出 (now*=p_i^{a_i}),当 (N) 拆分成 (1) ,则 (now) 就是满足条件的一个答案。

  • 为了提高效率,我们可以用线性筛求出小于 (N) 的质数。具体实现见代码。

Code

#include <bits/stdc++.h>
#define N 100000
int Prime[N+5],cnt,w,ans,a[N+5];
bool flag[N+5];
int tot=0;
void getprime(){//线筛
    for(int i=2;i<=N;i++){
        if(!flag[i]) Prime[++tot]=i;
        for(int j=1; i*Prime[j]<=N; j++){
            flag[i*Prime[j]]=1;
            if(i%Prime[j]==0) break;
        }
    }
}
bool isprime(int x){
    if(x==1) return false;
    if(x<=N) return !flag[x];//N以内的质数已经标记
    for(int i=1;Prime[i]*Prime[i]<=x;i++)
        if(x%Prime[i]==0) return false;
    return true;
}//
void dfs(int now,int p,int x){
// w分解后为剩下now  第p个质数  x为w分解出来的pi^(ai)l连乘
    if(now==1){//说明w分解完毕
        a[++cnt]=x;
        return;
    }//now-1为质数,恰好now=(now-1)^0+(now-1)^1
    if(isprime(now-1)&&now>Prime[p]) a[++cnt]=x*(now-1);
    for(int i=p;Prime[i]*Prime[i]<=now;i++){//枚举下一个选哪个质数 
        int pi=Prime[i];//pi为Prime[i]^i
        int sum=Prime[i]+1;//sum=pi^0+pi^1+.. 
        for(;sum<=now;pi*=Prime[i],sum+=pi) 
            if(now%sum==0) 
                dfs(now/sum,i+1,x*pi);
    }
}
void Solve(){
    getprime();
    while(scanf("%d",&w)!=EOF){
        cnt=0;
        dfs(w,1,1);
        printf("%d
",cnt);
        std::sort(a+1,a+cnt+1);
        for(int i=1;i<=cnt; i++)
            printf("%d ",a[i]);
        printf("
");
    } 
}
int main(){
    Solve();
    return 0;
}
原文地址:https://www.cnblogs.com/hbhszxyb/p/13414092.html