《算法竞赛·快冲300题》每日一题:“冰雹猜想II”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

冰雹猜想II” ,链接: http://oj.ecustacm.cn/problem.php?id=1744

题目描述

【题目描述】 冰雹猜想是指对于任意一个正整数,如果它是奇数,则对它乘3加1,如果是偶数,则除以2,最终会变成1,目前仍未找到反例。
  例如数字6。按照上述规则可以变成3、10、5、16、8、4、2、1,经过8次变换。
  现在给定数字n,求存在多少个数字变换n次得到1。。
【输入格式】 输入一个数字n(0≤n≤55)。
【输出格式】 输出一个数字表示答案。
【输入样例】

样例1
0

样例2
4

样例3
8

【输出样例】

样例1
1

样例2
1

样例3
4

题解

  本题显然用倒推,有2种情况:(1)“除以2”的倒推,是“乘2”;(2)“乘3加1”的倒推,是“减1除以3”,需要注意,此时应该判断“减1除以3”能除尽,而且是奇数。
  本题是路径问题,编码用DFS和BFS都行,DFS更简单一些。
【重点】 用BFS和DFS求解路径问题。

C++代码

  由于每次倒推有2种情况,在代码中每次DFS时继续做2次DFS,所以变换次数ans是 O ( 2 n ) O(2^n) O(2n)复杂度的,需要用long long类型。
  注意第6行是剪枝,如果倒推过程中又出现了1,说明这次倒推是无效的,直接返回。

#include
using namespace std;
int n;
long long ans=0;
void dfs(long long x,long long cnt){
    if(x==1 && cnt!=1)  return;          //又倒推回1,无效操作,不统计ans,直接返回
    if(cnt == n+1){                      //刚好n次,结束
        ans++;
        return;
    }
    dfs(2*x, cnt+1);                     //“除以2”的倒推:乘2
    if((x-1)%3==0 && ((x-1)/3)%2==1)     //(x-1)%3:能除尽,而且是奇数
        dfs((x-1)/3, cnt+1);             //“乘3加1”的倒推:减1除以3
}
int main(){
    cin>>n;
    dfs(1,1);
    cout<<ans;
}

Java代码

import java.util.Scanner;
public class Main {
    static int n;
    static long ans = 0;
    public static void dfs(long x, long cnt) {
        if (cnt != 1 && x <= 1) return;       //又倒推回1,无效操作,不统计ans,直接返回
        if (cnt == n + 1) {                   //刚好n次,结束
            ans++;
            return;
        }
        dfs(2 * x, cnt + 1);                                //“除以2”的倒推:乘2
        if ((x - 1) % 3 == 0 && ((x - 1) / 3) % 2 == 1)     //(x-1)%3:能除尽,而且是奇数
            dfs((x - 1) / 3, cnt + 1);                      //“乘3加1”的倒推:减1除以3
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        dfs(1, 1);
        System.out.println(ans);
    }
}

Python代码

n = int(input())
ans = 0
def dfs(x, cnt):
    global ans
    if cnt != 1 and x <= 1:  return      #又倒推回1,无效操作,不统计ans,直接返回
    if cnt == n+1:
        ans += 1
        return
    dfs(2*x, cnt+1)                           #“除以2”的倒推:乘2
    if (x-1)%3 == 0 and ((x-1)//3)%2 == 1:    # (x-1)%3:能除尽,而且是奇数
        dfs((x-1)//3, cnt+1)                  # “乘3加1”的倒推:减1除以3
dfs(1,1)
print(ans)

你可能感兴趣的:(算法竞赛快冲300题,算法)