其他分享
首页 > 其他分享> > P4397 【[JLOI2014]聪明的燕姿】

P4397 【[JLOI2014]聪明的燕姿】

作者:互联网

先讲一些东西

1.算数基本定理:任何一个大于1的自然数N,都可以唯一分解成有限个质数的乘积N=P₁^a₁ P₂a₂…Pnan,这里P₁<P₂<…<Pn均为质数,其诸指数ai是正整数。

2.约数和定理:对于任意一个大于1的正整数N可以分解正整数:N=P₁^a₁ P₂a₂…Pnan,则由约数个数定理可知N的正约数有(a₁+1)(a₂+1)(a₃+1)…(an+1)个,那么N的(a₁+1)(a₂+1)(a₃+1)…(an+1)个正约数的和为f(N)=(P₁0+P₁1+P₁2+…P₁a₁)(P₂0+P₂1+P₂2+…P₂a₂)…

就是数轮题

代码↓

#include <cstdio>           //头文件不解释
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#ifndef rr
#define rr register
#endif
#define ll long long
using namespace std;
const ll N=1e10;                //找s以内的素数
ll b[500005],top,ans,a[500005];
bool f[500005];
ll x;
inline int xxs(){                     //找s以内的素数
	f[1]=1;
    for(rr ll i=2; i<=sqrt(N);++i) {
        if(!f[i])
            b[++top]=i;
        for(rr ll j=1;j<=top;++j) {
        	if(b[j]*i>sqrt(N))
        		break;
            f[i*b[j]]=1;
            if(i%b[j]==0)
                break;
        }
    }
}
inline bool ss(ll x) {              //判断素数
    for(rr ll i=2;i<=sqrt(x);++i)
        if(x%i==0)
            return 0;
    return 1;
}
inline void dfs(ll i,ll n,ll shu) {       //搜索约数和
    if(n==1) {
        a[++ans]=shu;
        return;
    }
    if(i>top||b[i]>=x-1)
        return;
    if(n-1>=b[i]&&ss(n - 1))
        a[++ans]=(n-1)*shu;
    for(rr int j=i;b[j]*b[j]<=n;++j) {
        ll tot=b[j]+1,tmp=b[j];
        for(;tot<=n;tmp*=b[j],tot+=tmp)
            if(n%tot==0)
                dfs(j+1,n/tot,shu*tmp);
    }
}
signed main() {
	xxs();                    //找素数
    while(scanf("%lld",&x)==1) {   //输入
        if(x==1) {
            printf("1\n1\n");    //1的情况单独判断
            continue;
        }
        ans=0;
        dfs(1,x,1);           //深搜解
        printf("%lld\n",ans);
        sort(1+a,a+ans+1);
        for(rr ll i=1;i<=ans;++i) 
        	printf("%lld ",a[i]);
        if(ans!=0)              //注意格式
            putchar('\n');
    }
}

标签:约数,燕姿,JLOI2014,rr,ll,素数,include,500005,P4397
来源: https://www.cnblogs.com/lieberdq/p/12774913.html