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

本文介绍了一种用于寻找特定数字所有可能的带分数表示形式的搜索算法,该算法利用了递归和剪枝技术,确保数字1至9在每种表示中恰好出现一次。通过实例展示了如何实现这一算法,并提供了完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源: 第四届蓝桥杯省赛C++B组
算法标签 递归搜索剪枝

题目描述

100 可以表示为带分数的形式:100=3+69258714
还可以表示为:100=82+3546197
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。

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

输入格式

一个正整数。

输出格式

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

数据范围

1≤N<106

输入样例1:

100

输出样例1:

11

输入样例2:

105

输出样例2:

6

思路

有题可知带分数中,数字 1∼9 分别出现且只出现一次
且带分数的特性为n=a+b/c,换言之即为n*c=a*c+b;

因为最耿直的做法我们可以将1-10直接暴搜且限制每个数字只出现一次,然后判断是否符合n*c=a*c+b;即可。

C++ 代码
#include<iostream>

using namespace std;

const int N=1e6+10;
bool st[N];//判断当前数是否被使用
int n,num[N],cnt;

int sum(int l,int r)//取出num中存储的数值,计算a,b,c的数值
{
    int t=0;
    for(int i=l;i<=r;i++)
        t=t*10+num[i];
    return t;
}
void dfs(int u)
{
    if(u>9)//如果1到9放置完毕
        {
            for(int i=1;i<=9;i++)
                for(int j=i+1;j<=9;j++)//用二维遍历所有的长度可能性
                    {
                        int a=sum(1,i);
                        int b=sum(i+1,j);
                        int c=sum(j+1,9);//a,b,c的长度被分成三段限制
                        if(n*c==a*c+b)cnt++;//如果满足判断条件则加1
                    }
            return ;
        }
    for(int i=1;i<=9;i++)//暴搜1-9的排列
        {
            if(!st[i])//如果当前数字没有被选择
                {
                    st[i]=true;//选择,下一次不能再被使用
                    num[u]=i;//放入数组num
                    dfs(u+1);//判断下一个数字
                    num[u]=0;
                    st[i]=false;
                }
        }
}
int main()
{
    cin>>n;
    dfs(1);//从1开始跑,绝对够直白
    cout<<cnt;//输出有多少种满足条件的带分数
    return 0;
}
#include<iostream>

using namespace std;

const int N = 1e6+10;

bool st[N];
int n,num[N],ans;

int sum(int l,int r){
        int t=0;
        for(int i=l;i<=r;i++){
                t=t*10+num[i];
        }

        return t;
}

void dfs(int u){
        if(u>9){
                for(int i=1;i<=9;i++){
                        for(int j=i+1;j<=9;j++){
                                int a=sum(1,i);
                                int b=sum(i+1,j);
                                int c=sum(j+1,9);
                                if(n*c==a*c+b)
                                        ans++;
                        }
                }
        }
        else {
                for(int i=1;i<=9;i++){
                        if(!st[i]){
                                st[i]=true;
                                num[u]=i;
                                dfs(u+1);
                                num[u]=0;
                                st[i]=false;
                        }
                }
        }
}

int main(){
        cin>>n;
        dfs(1);
        cout<<ans<<endl;

        return 0;
}

### 第十四届蓝桥杯 C++ B详情 #### 比题目概述 第十四届蓝桥杯C++ B的题目涵盖了多个算法和数据结构的知识点。这些题目旨在考察选手的基础编程能力以及解决实际问题的能力[^2]。 #### 题目难度分析 对于部分题目,可以采用较为简单的解法来获取一定分数。例如,在处理某些特定类型的字符串匹配问题时,虽然最直观的方法是使用双重`for`循环遍历所有可能的子串合,但这会导致时间复杂度过高而无法在规定时间内完成计算(即TLE, Time Limit Exceeded)。然而,在竞环境中,这种方法仍然可以帮助参者获得一些测试用例的部分得分[^4]。 #### 参规则要点 为了确保公平竞争并促进学习交流,比期间允许使用计算器辅助运算工具。这一设置体现了主办方希望降低不必要的手工计算负担,使参与者能够更专注于逻辑思考与编码实现上[^3]。 #### 成绩查询方式 关于具体的成绩公布时间和途径,请关注官方渠道发布的最新通知。通常情况下,成绩会在后一段时间内由委会统一发布,并可通过指定网站或平台进行查询。 ```python # 示例:如何在线提交代码至评测系统(假设) import requests def submit_code(problem_id, code): url = "https://example.com/submit" payload = { 'problemId': problem_id, 'code': code } response = requests.post(url, data=payload) return response.json() # 使用示例 result = submit_code(1001, """ #include <iostream> using namespace std; int main() { cout << "Hello World!"; return 0; } """) print(result) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俺叫西西弗斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值