第四届蓝桥杯省赛 C++ B组 - 带分数

简介: 第四届蓝桥杯省赛 C++ B组 - 带分数

问题描述


100 可以表示为带分数的形式:100=3+69258/714

还可以表示为:100=82+3546/197

注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。

类似这样的带分数,100 有 11 种表示法。


输入格式

一个正整数。


输出格式

输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。


数据范围

1≤N<106


输入样例1:

100

输出样例1:

11

输入样例2:

105

输出样例2:

6


暴力法

#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 10;
int res[N]; //存储结果
bool st[N]; //表示元素是否用过
int cnt = 0;
//计算每一段的总数
int calc(int l, int r) {
  int num = 0;
  for (int i = l; i <= r; i++) {
    num = num * 10 + res[i];
  }
  return num;
}
//将全排列的数组分成三段进行判断
void dfs(int k) {
  if (k == 9) {
    for (int i = 0; i < 7; i++) {
      for (int j = i + 1; j < 8; j++) {
        int a = calc(0, i);
        int b = calc(i + 1, j);
        int c = calc(j + 1, 8);
        if (a * c + b == n * c) //c++中除法是整除,所以要转换为乘法
          cnt++;
      }
    }
    return;
  }
  //进行全排列
  for (int i = 1; i <= 9; i++) {
    if (!st[i]) {
      st[i] = true;
      res[k] = i;
      dfs(k + 1);
      st[i] = false;
    }
  }
}
int main() {
  cin >> n;
  dfs(0);
  cout << cnt << endl;
  return 0;
}


暴力法(内置函数)

next_permutation() 蓝桥杯允许使用

#include<bits/stdc++.h>
using namespace std;
int n;
const int N=10;
int res[N]; //存储结果
int cnt=0;
//计算每一段的总数
int calc(int l,int r)
{
    int num=0;
    for(int i=l;i<=r;i++)
    {
        num=num*10+res[i];
    }
    return num;
}
int main()
{
    cin>>n;
    for(int i=0;i<9;i++)
        res[i]=i+1;
    do{
        for(int i=0;i<7;i++)
        {
            for(int j=i+1;j<8;j++)
            {
                int a=calc(0,i);
                int b=calc(i+1,j);
                int c=calc(j+1,8);
                if(a*c+b==n*c)
                    cnt++;
            }
        }
    }while(next_permutation(res,res+9));  //调用函数进行全排列
    cout<<cnt<<endl;
    return 0;
}


优化


先枚举 a ,再枚举 c ,直接通过 a 和 c 求出 b ,就不用再枚举 b 了。然后判断 b 是否满足要求,如果 b 中的每一位都没有被 a 和 c 所用过并且 1 到 9 都被已经用过了,则满足要求,答案总数加 1。


举个例子,假设 a 枚举到了 82,然后枚举 c,而 c 枚举到了 3456,则去计算 b,根据公式推导,b 等于 n*c-a*c,从而算出 197。接下来就进行判断,首先 abc 都不能为 0 这是肯定的,然后需要判断 b 是否用了剩下没有用过的数字,如果出现了 a 和 c 中的数字则不满足条件,并且 b 要将剩下没用过的数字全部用上才满足条件。



#include <bits/stdc++.h>
using namespace std;
const int N = 10;
int n, ans = 0;
bool st[N], backup[N];
//判断是否满足条件
bool check(int a, int c) {
    //计算b
    //这里需要long long是因为防止n为10的6次方时与c相乘后爆int,导致b为负数,x也会为负数
    //x为负数的话,backup就会数组越界,所以要加long long
  long long b = n * (long long)c - a * c;
  //a,b,c都不能为0
  if (!b || !a || !c)
    return false;
  //因为原状态数组不能改变,为了后续判断,就新建一个状态数组用于判断
  memcpy(backup, st, sizeof(st));
    //判断b中的每一位数字
  while (b) {
    int x = b % 10;
    if (!x || backup[x])
      return false;
    b /= 10;
    backup[x] = true;
  }
  //判断是否1-9都使用过
  for (int i = 1; i <= 9; i++) {
    if (!backup[i])
      return false;
  }
  return true;
}
//枚举c
void dfs_c(int x, int a, int c) {
  if (x > 9)
    return;
  if (check(a, c))
    ans++;
  for (int i = 1; i <= 9; i++) {
    if (!st[i]) {
      st[i] = true;
      dfs_c(x + 1, a, c * 10 + i);
      st[i] = false;
    }
  }
}
//枚举a
void dfs_a(int x, int a) {
  if (a >= n)
    return;
  if (a)
    dfs_c(x, a, 0);
  for (int i = 1; i <= 9; i++) {
    if (!st[i]) {
      st[i] = true;
      dfs_a(x + 1, a * 10 + i);
      st[i] = false;
    }
  }
}
int main() {
  cin >> n;
  dfs_a(0, 0);
  cout << ans << endl;
  return 0;
}
目录
相关文章
|
1月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
1月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
1月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
1月前
|
机器学习/深度学习 算法 关系型数据库
第十五届蓝桥杯C++B组省赛
第十五届蓝桥杯C++B组省赛
71 14
|
1月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
35 5
|
6月前
|
算法 测试技术 C++
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
|
6月前
|
算法 C++ 数据格式
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
|
6月前
|
数据安全/隐私保护 C++
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题
|
9天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
36 4
|
10天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
33 4