带分数:http://lx.lanqiao.org/problem.page?gpid=T26
问题描述
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枚举全排列,但觉得和循环差别不大,就直接用循环了
n=i+((n-i)*j)/j
枚举i和j,判断i,j,(n-i)*j是否满足题目要求即可
#include <cstdio>
#include <algorithm>
using namespace std;
int n,ans,a[11],atop,t,b[11],btop,c[11],ctop,num,tmp;
bool used[11];
bool judge(int x[],int& xtop) {
while(t) {
if(used[t%10])
return false;
used[x[++xtop]=t%10]=true;
t/=10;
}
return true;
}
bool isOK() {
for(int i=1;i<10;++i)
if(!used[i])
return false;
return true;
}
int main() {
int i,j;
for(i=0;i<11;++i)
used[i]=false;
used[0]=true;
while(1==scanf("%d",&n)) {
ans=0;
for(i=1;i<n;++i) {
atop=-1;
t=i;
if(judge(a,atop)) {
num=n-i;
for(j=1;j<10000&&(tmp=num*j)<98765432;++j) {//【注意】num*j有可能爆int,本地测试n=1000000都运行错误,提交却AC,不知是否是没出极限数据
btop=-1;
t=j;
if(judge(b,btop)) {
t=tmp;
ctop=-1;
if(judge(c,ctop)&&isOK())
++ans;
while(ctop>=0)//这些复原本来可以复制副本,最后拷会去即可,结果只想到更麻烦的方法
used[c[ctop--]]=false;
}
while(btop>=0)
used[b[btop--]]=false;
}
}
while(atop>=0)
used[a[atop--]]=false;
}
printf("%d\n",ans);
}
return 0;
}