2019.2.18写
解题思路
首先感谢这些大神的博客,附上传送门:带分数https://blog.csdn.net/acmman/article/details/19282173
全排列https://blog.csdn.net/summerxiachen/article/details/60579623#commentBox
这题的解题方法是“全排列”+“剪枝”。先通过全排列得到1~9这九位数的每一次的变化,在每一次的变化中去判断是否满足题目要求的" num = a + b/c "。剪枝的过程是通过" num = a + b/c "和题意判断出 a<num ; b%c==0。注意的是:a从1~9中如果取用了n位,那么b一定只能从剩下的(9-n)中取用至少(9-n)/2位,最多(9-n)-1位,最后才是c取用的位数。
问题描述
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
附上代码
#include<iostream>
using namespace std;
int a[10]={0,1,2,3,4,5,6,7,8,9};
int num=0;
int ans=0;//统计总数
int main()
{
void AllParmutation(int,int);//全排列
void Found(int);//对每一次的排列进行筛选
int sum(int,int);//转换成相应的一个多位整数
cin>>num;
AllParmutation(1,10);
cout<<ans<<endl;
return 0;
}
int sum(int start,int end)
{
int sum=0;
for(int i=start;i<end;i++)
sum=sum*10+a[i+1];
return sum;
}
void Found(int n)
{ //位数从1~9之间选
for(int i=1;i<n;i++)
{
int a=sum(0,i);//确定a
if(a>=num)
return;
for(int j=i+(n-i)/2;j<n-1;j++)
{
int b=sum(i,j);//确定b
int c=sum(j,n-1);//确定c
if((b>c)&&(b%c==0)&&(num==a+b/c))
ans++;
}
}
}
void AllParmutation(int start,int n)
{
if(start==n)
{
Found(n);
}
for(int i=start;i<n;i++)
{
swap(a[start],a[i]);
AllParmutation(start+1,n);
swap(a[start],a[i]);
}
}