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