bzoj3629(洛谷P4397): [JLOI2014]聪明的燕姿(数学+深搜)

题意

求约数个数和为 n n 的数有哪几个


题解

首先我们来看一个定理:约数和定理(下文会用到)

对于任意一个大于1的正整数N可以分解正整数:x=P1a1P2a2Pnan ,则由约数个数定理可知 x x 的正约数有 (a1+1)(a2+1)(a3+1)(an+1)个,那么 x x (a1+1)(a2+1)(a3+1)(an+1) 个正约数的和为 f(x)=(P01+P11+P21+Pa11)(P02+P12+P22+Pa22)(P0n+P1n+P2n+Pann) f ( x ) = ( P 1 0 + P 1 1 + P 1 2 + … P 1 a 1 ) ( P 2 0 + P 2 1 + P 2 2 + … P 2 a 2 ) … ( P n 0 + P n 1 + P n 2 + … P n a n )

因此递归搜索解决,枚举 pi p i ,再对应枚举 ai a i

约数的和为 n n ,即 f(x)=n ,所以 x<n x < n (否则都会至少大于等于 n+1 n + 1

然后就可以愉快的深搜了
如果此时刚好可以表示成 一个质数+1,那么结果就会有 当前的结果 * 质数
然后对于每个未搜索过的质数,枚举 ai a i 再去深搜就可以了


代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
#define ll long long
#define N 100010
ll n,ans[N],phi[N],s1[N];
int num=0,tot,notprime[N],prime[N];
inline void getprime(){
    notprime[1]=1;
    for(int i=2;i<=100000;i++){
        if(!notprime[i]) prime[++tot]=i;
        for(int j=1;j<=tot && prime[j]*i<=100000;j++){
            notprime[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}
inline bool isprime(ll x){
    if(x<=100000) return !notprime[x];
    for(int i=1;i<=tot;i++) if(x%prime[i]==0) return 0;
    return 1;
}
void dfs(int last,ll now,ll s){         //解决约数个数和为 s 的问题 
    if(s==1){ans[++num]=now;return;}
    if(s-1>prime[last] && isprime(s-1))   
        ans[++num]=now*(s-1);
    for(int i=last+1;prime[i]*prime[i]<=s;i++){
        for(int tnum=prime[i]+1,t=prime[i];tnum<=s;t*=prime[i],tnum+=t){
            if(s%tnum==0) 
                dfs(i,now*t,s/tnum);
        }
    }
}
int main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    getprime();
    while(scanf("%lld",&n)>0){
        num=0;dfs(0,1,n);
        printf("%d\n",num);
        sort(ans+1,ans+num+1);
        for(int i=1;i<=num;i++) printf("%lld%c",ans[i],i==num?'\n':' ');
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值