zoukankan      html  css  js  c++  java
  • 找伙伴

    找伙伴(数论 (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;
    }
    
  • 相关阅读:
    css3新特性总结
    ES6常用特性总览
    前端第一次面试
    将一个行数在主线程执行的4中方法
    判断邮箱格式和图片压缩
    上传图片的实现
    导航右侧添加按钮、隐藏导航条和状态栏
    从相册选取图片展示并实现自定义事件
    cell添加选中时的背景图片、显示图片和图片自适应框的大小
    设置键盘无色和状态栏风火轮、屏幕截图
  • 原文地址:https://www.cnblogs.com/hbhszxyb/p/13414092.html
Copyright © 2011-2022 走看看