AcWing1296. 聪明的燕姿
聪明的燕姿
解题思路:
首先我们肯定要用到约数之和定理
但是有个问题就是要怎么用
根据经验得知,约数最多也就六七个左右,不然直接就超了s的范围。所以我们考虑用爆搜来做
但是用爆搜的话还是要优化一下思路和用什么顺序去搜索。
顺序:
按照p和α的顺序来枚举
一旦s%这个当前的乘积==0(dfs的精髓)
那才能跳到下一层循环因为这样才符合约数和定理
dfs的精髓:当前条件满足,然后递归到下一层。到最后一层的时候又满足条件。然后跳出递归
可能要想一些剪枝:
- 当s等于1+p的时候,直接就得到一个答案。这样就可以少遍历几个
小于s的质数的个数有s除以logn个
时间复杂度:\(O(10\sqrt{S}*100)\)
十个约数,然后再判断质数的个数。k组数据
y总的代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 50000;
int primes[N], cnt;
bool st[N];
int ans[N], len;
void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] * i <= n; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
bool is_prime(int x)
{
    if (x < N) return !st[x];
    for (int i = 0; primes[i] <= x / primes[i]; i ++ )
        if (x % primes[i] == 0)
            return false;
    return true;
}
void dfs(int last, int prod, int s)
{
    if (s == 1)
    {
        ans[len ++ ] = prod;
        return;
    }
    if (s - 1 > (last < 0 ? 1 : primes[last]) && is_prime(s - 1))
        ans[len ++ ] = prod * (s - 1);  // 不可以写primes[last]因为可能是第一个
    for (int i = last + 1; primes[i] <= s / primes[i]; i ++ )
    {
        int p = primes[i];
        for (int j = 1 + p, t = p; j <= s; t *= p, j += t)
            if (s % j == 0)
                dfs(i, prod * t, s / j);
    }
}
int main()
{
    get_primes(N - 1);
    int s;
    while (cin >> s)
    {
        len = 0;
        dfs(-1, 1, s);
        cout << len << endl;
        if (len)
        {
            sort(ans, ans + len);
            for (int i = 0; i < len; i ++ ) cout << ans[i] << ' ';
            cout << endl;
        }
    }
    return 0;
}
解题技巧创造出来
算法创造出来比较少
自己的代码
#include<cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50000 + 10;
int ans[maxn], len, cnt;
int primes[maxn];
bool st[maxn];
void get_primes(int n)
{
    for(int i = 2; i <= n; i++) // 求约数不能折半
    {
        if(!st[i]) primes[cnt++] = i;
        for(int j = 0; primes[j] * i <= n ; j ++)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0) break;
        }
    }
}
bool is_prime(int n)
{
    if(n < maxn) return !st[n];
    for(int i = 0; primes[i] <= n / primes[i]; i++)
    {
        if(n % primes[i] == 0) return false;
    }
    return true;
}
void dfs(int last, int prod, int s)
{
    if(s == 1)
    {
        ans[len++] = prod;
        return ;
    }
    if(is_prime(s - 1) && s - 1 > (last < 0 ? 1 : primes[last])) ans[len++] = prod * (s - 1); // primes[last + 1]的话可能会出错
    for(int i = last + 1; primes[i] <= s / primes[i]; i++)
    {
        int p = primes[i];
        for(int j = 1 + p, t = p; j <= s; t*=p, j += t)
        {
            if(s % j == 0)  dfs(i, prod * t, s / j);
        }
    }
}
int main()
{
    get_primes(maxn);
    int s;
    while(~scanf("%d", &s))
    {
        len = 0;
        dfs(-1, 1, s);
        cout << len << endl;
        if(len)
        {
            sort(ans, ans + len);
            for(int i = 0; i < len ; i++) printf("%d ", ans[i]);
            printf("\n");
        }
    }
    return 0;
}
AcWing1296. 聪明的燕姿的更多相关文章
- BZOJ_3629_[JLOI2014]聪明的燕姿_dfs
		BZOJ_3629_[JLOI2014]聪明的燕姿_dfs Description 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 ... 
- bzoj3629 / P4397 [JLOI2014]聪明的燕姿
		P4397 [JLOI2014]聪明的燕姿 根据唯一分解定理 $n=q_{1}^{p_{1}}*q_{2}^{p_{2}}*q_{3}^{p_{3}}*......*q_{m}^{p_{m}}$ 而$ ... 
- P4397 [JLOI2014]聪明的燕姿
		P4397 [JLOI2014]聪明的燕姿 题目背景 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 我听见风来自地铁和人海 我排 ... 
- 【LG4397】[JLOI2014]聪明的燕姿
		[LG4397][JLOI2014]聪明的燕姿 题面 洛谷 题解 考虑到约数和函数\(\sigma = \prod (1+p_i+...+p_i^{r_i})\),直接爆搜把所有数搜出来即可. 爆搜过 ... 
- [补档][JLOI 2017]聪明的燕姿
		[NOI 2008]假面舞会 题目 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 我听见风来自地铁和人海 我排着队拿着爱的号码牌 ... 
- 聪明的燕姿[JLOI2014]
		题目描述 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 我听见风来自地铁和人海 我排着队拿着爱的号码牌 城市中人们总是拿着号码牌 ... 
- [JLOI2014]聪明的燕姿(搜索)
		城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁. 可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字 S, ... 
- bzoj 3629 [JLOI2014]聪明的燕姿(约数和,搜索)
		[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3629 [题意] 给定S,找出所有约数和为S的数. [思路] 若n=p1^a1*p2^a ... 
- bzoj3629[JLOI2014]聪明的燕姿
		http://www.lydsy.com/JudgeOnline/problem.php?id=3629 搜索. 我们知道: 如果$N=\prod\limits_{i=1}^{m}p_{i}^{k_{ ... 
随机推荐
- SQL Server 2012 安装完成后,无法通过 sa账号登录
			1.打开 SQL server configuration manager 2.打开 SQLserver 网络配置 打开 SQLSERVER的协议 3.右击 TCP/IP协议,选择 IPALL ,在 ... 
- [python之路]变量和字符编码
			变量和字符编码 #变量##声明变量```#_*_coding:utf-8_*_ name = "Tom"```上述代码声明了一个变量,变量名为: name,变量name的值为:&q ... 
- Windows系统-cmd中的tracert命令
			大部分同学都是用的Linux系统来测试网络命令相关工具,我用Windows10系统来测试tracert. tracert:也被称为Windows路由跟踪实用程序,在命令提示符(cmd)中 ... 
- java架构之路-(微服务专题)初步认识微服务与nacos初步搭建
			历史演变: 以前我们都是一个war包,包含了很多很多的代码,反正我开始工作的时候做的就是这样的项目,一个金融系统,代码具体多少行记不清楚了,内部功能超多,但是实际能用到的不多,代码冗余超大,每次部署大 ... 
- Go语言实现:【剑指offer】二叉搜索树与双向链表
			该题目来源于牛客网<剑指offer>专题. 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. Go语言实现: type T ... 
- Speech Super Resolution Generative Adversarial Network
			博客作者:凌逆战 博客地址:https://www.cnblogs.com/LXP-Never/p/10874993.html 论文作者:Sefik Emre Eskimez , Kazuhito K ... 
- javascript get set读取器
			class Person{ constructor(name, id){ let _name = name, _id = id; Object.defineProperties(this, { nam ... 
- 给 iTerm 终端设置代理
			本文介绍如何为自己的终端设置代理,从而实现在命令行中访问Google. 1. 背景 当你使用SS FQ时,大部分浏览器都可以成功访问Google,但是在命令行下执行curl https://www.g ... 
- linux中的正则表达式知识梳理
			1. 正则表达式 1.1 正则表达式使用 正则表达式是开发者为了处理大量的字符串和文本而定义的一套规则和方法,使用正则表达式可以提高效率,快速获取想要的内容. 正则表达式常用于linux三剑客grep ... 
- docker实战部署Javaweb项目
			一.部署环境说明 docker服务版本:version 18.09.0nginx服务版本:version: nginx/1.15.10redis服务版本:version: redis/5.0.3tom ... 
