bzoj3629

Posted 123456

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3629相关的知识,希望对你有一定的参考价值。

dfs

跟上道题很像有木有

同样地,我们暴力枚举约数

根据约数和公式,得出$S=\prod_{i=1}^{n}{(1+p+p^{2}+...+p^{a_{i}})}$

所以每次我们暴力枚举是哪个约数,次数是多少,然后爆搜

如果剩下的约数和$S-1$是质数,那么说明约数只剩下一个大质数,直接统计答案结束即可

因为一个数不可能大于自己的约数和,所以大于$sqrt(S)$的约数只能有一个

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 5;
int s, sqrts;
int p[N], mark[N], ans[N << 1];
void shaker() {
    for(int i = 2; i < N; ++i) {
        if(!mark[i]) {
            p[++p[0]] = i;
        }
        for(int j = 1; j <= p[0] && i * p[j] < N; ++j) {
            mark[i * p[j]] = 1;
            if(i % p[j] == 0) {
                break;
            }
        }
    }
}
bool judge(int x) {
    if(x == 1) {
        return 0;
    }
    if(x < N) {
        return !mark[x];
    }
    for(int i = 1; p[i] * p[i] <= x; ++i) {
        if(x % p[i] == 0) {
            return 0;
        }
    }
    return 1;
}
void dfs(int last, int tot, int sum) {
    if(tot == 1) {
        ans[++ans[0]] = sum;
        return;
    }
    if(tot - 1 > sqrts && judge(tot - 1)) {
        ans[++ans[0]] = sum * (tot - 1);
    }
    for(int i = last + 1; p[i] <= sqrts; ++i) {
        int t = p[i], all = 1;
        for(int j = 1; all + t <= tot; ++j) {
            all += t;
            if(tot % all == 0) {
                dfs(i, tot / all, sum * t);
            }
            t *= p[i];
        }
    }
}
int main() {
    shaker();
    while(scanf("%d", &s) != EOF) {
        ans[0] = 0;
        sqrts = sqrt(s);
        dfs(0, s, 1);
        sort(ans + 1, ans + ans[0] + 1);
        printf("%d\n", ans[0]);
        for(int i = 1; i < ans[0]; ++i) {
            printf("%d ", ans[i]);
        }
        if(ans[0]) {
            printf("%d\n", ans[ans[0]]);
        }
    }
    return 0;
}
View Code

 

以上是关于bzoj3629的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3629 [JLOI2014]聪明的燕姿(约数和,搜索)

bzoj 3629

bzoj 3629 [JLOI2014]聪明的燕姿——约数和定理+dfs

bzoj 3629: [JLOI2014]聪明的燕姿线性筛+dfs

BZOJ1912 APIO2010 洛谷P3629 巡逻

BZOJ 3629 JLOI2014 聪明的燕姿 约数和+DFS