蓝桥杯 历届试题 带分数(搜索)

历届试题 带分数  

时间限制:1.0s   内存限制:256.0MB
问题描述

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

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

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

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

输入格式

从标准输入读入一个正整数N (N<1000*1000)

输出格式

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

注意:不要求输出每个表示,只统计有多少表示法!

样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6

 
  一道搜索题,用递归遍历所有情况。符合条件的累加计数。
  一开始没思路,借鉴了网上的解答。给出链接:http://bbs.csdn.net/topics/390448276 。借鉴了12楼 nono_lonely 的代码。
  我选择的做法是将N分成两部分,左边的是整数部分,右边的根据一定的规则化成分数形式。只要这个过程符合规则,则计数+1。
 
  下面是第一次代码,与原作者代码大相径庭,但好歹AC了,调了2个小时,主要是细节问题,代码有些臃肿,后面我会再优化。
 
  1 #include <iostream>
  2 #include <string.h>
  3 using namespace std;
  4 int N;
  5 int _count;
  6 int le,ri; //左边的数,右边的数
  7 int left_digits,right_digits;   //左边数的位数,右边数的位数
  8 
  9 struct CB{
 10     char c;     //存储字符
 11     bool isu;   //有没有被使用
 12 }cb[10];
 13 
 14 void flags(int n)   //对该数进行标记
 15 {
 16     while(n){
 17         int t;
 18         t=n%10;
 19         cb[t].isu = true;
 20         n/=10;
 21     }
 22 }
 23 void unflags(int n) //取消标记
 24 {
 25     while(n){
 26         int t;
 27         t=n%10;
 28         if(t==0)
 29             cb[t].isu = true;
 30         else
 31             cb[t].isu = false;
 32         n/=10;
 33     }
 34 }
 35 int check(int n)
 36 {
 37     CB cb2[10];
 38     memcpy(cb2,cb,sizeof(cb));
 39     while(n){
 40         int t;
 41         t=n%10;
 42         if(cb2[t].isu || t==0){
 43             return 0;
 44         }
 45         cb2[t].isu=true;
 46         n/=10;
 47     }
 48     return 1;
 49 }
 50 int use(int n)  //返回使用的位数
 51 {
 52     int length=0;
 53     while(n){
 54         length++;
 55         n/=10;
 56     }
 57     return length;
 58 }
 59 bool all_use()
 60 {
 61     for(int i=1;i<=9;i++){
 62         if(!cb[i].isu)
 63             return false;
 64     }
 65     return true;
 66 }
 67 void ConstructFraction(int depth,int mol) //构造分数。depth为分子的位数,不能超过剩余位数的一半。mol为本次的分子数,如果本次能构造成功,则计数+1。
 68 {
 69     if(depth <= right_digits/2){
 70         for(int i=mol;i<=mol*10-1;i++){
 71             if(check(i)){
 72                 flags(i);
 73                 int deno = ri*i;   //确定分母
 74                 if(check(deno)){
 75                     flags(deno);
 76                     //分母通过验证,在判断9个数字是否都用上了
 77                     if(all_use()){   //都用上了,计数+1
 78                         _count++;
 79                         //cout<<N<<'='<<le<<'+'<<deno<<'/'<<i<<endl;
 80                     }
 81                     unflags(deno);
 82                 }
 83                 unflags(i);
 84             }
 85         }
 86         ConstructFraction(depth+1,mol*10);
 87     }
 88 }
 89 int main()
 90 {
 91     while(cin>>N){
 92         _count=0;
 93         for(int i=1;i<=N-1;i++){
 94             le=i;
 95             ri = N-le;
 96             cb[0].isu = true;
 97             for(int j=1;j<=9;j++){  //初始化
 98                 cb[j].c = '0'+j;
 99                 cb[j].isu = false;  //初始化时每个字符都定义为没使用
100             }
101             if(check(le)){    //核对左边的数是否符合规则
102                 flags(le);    //对左边的数使用过的位进行标记
103                 left_digits = use(le);    //返回使用的位数
104                 right_digits = 9-left_digits;   //剩余的位数
105                 ConstructFraction(1,1);
106                 unflags(le);
107             }
108         }
109         cout<<_count<<endl;
110     }
111     return 0;
112 }

Freecode : www.cnblogs.com/yym2013

原文地址:https://www.cnblogs.com/yym2013/p/3514633.html