问题描述
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
本来参考网上dfs+剪枝算法。看的都要晕了。。太难了。。。
终于找到了一篇不用dfs算法的文章!!
参考:http://www.2cto.com/kf/201409/334820.html
稍加分析:
输入为N,则N = i+j/k,只需要找到满足i,j,k三个数中含有1~9全部数字即可。i的取值范围为1~N,j/k的值必定为整数。那么j的长度(化为字符串)一定是k长度的两倍或两倍以上。i的最小长度为1,j和k的长度之和最大为8,k的最大长度为4,那么k的取值范围为1~9999。i,k的范围已经确定。可以开始遍历了。j = (N-i)*k,即可求出j。然后再判断i,j,k是否满足条件即可。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
using namespace std;
int judge(int i,int j,int k)
{
int a[10] = {0};
while(i) //i,j,k三个数中数字不重复
{
a[i%10]++;
if(a[i%10] > 1)
return 0;
i /= 10;
}
while(j)
{
a[j%10]++;
if(a[j%10] > 1)
return 0;
j /= 10;
}
while(k)
{
a[k%10]++;
if(a[k%10] > 1)
return 0;
k /= 10;
}
if(a[0] > 0) //i,j,k中均不含数字0
return 0;
for(int l = 1;l < 10;l++) //i,j,k三个数包含1~9全部数字
{
if(a[l] == 0)
return 0;
}
return 1;
}
int main()
{
int N,i,k,j,count = 0;
cin>>N; //N = i + j/k;
for(i = 1;i < N;i++) //i的变化范围为1~N-1,
{
for(k = 1;k<9999;k++)
{
j = (N-i)*k;
if(judge(i,j,k)) //判断i,j,k是否满足条件
count++;
}
}
cout<<count<<endl;
return 0;
}