您的位置:首页 > 其它

历届试题 带分数(全排列+枚举)

2016-05-05 22:56 281 查看
问题描述

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

最近看了一些ACM的书要吐血了,这题刚看的时候居然有点蒙,现设a+b/c==n, 问题出在n上,就是我想n那么大枚举完a再考虑b, c肯定要超时怎么行呢!然而别忘了一点,就是说n可以很大,可以一直变,但是有一点不变,那就是1~9的排列数,你这些其实只能从1~9的排列里面选出数来,比如随便167385492,那么就是说a取前面几个数,b接着取几个数,剩下的给c,现在的情况就是变得跟n没多大关系了,然后根据限制条件(1)a<n(2)b<c(3)b%c==0可以筛除一大部分数据,就是枚举的时候注意一下技巧。
# include <cstdio>
# include <cmath>
# include <algorithm>
using namespace std;
int n, s[10];
int main(){
int i, j, k, a, b, c, ans;
scanf("%d", &n);
ans=0;
for(i=0; i<=8; i++){
s[i]=i+1;
}
do{
a=0;
for(i=0; i<=6; i++){
a=10*a+s[i];
if(a>=n){
break;
}
b=0;c=0;
for(j=i+1; j<=(8-i+1)/2+i; j++){//因为b>c所以b取剩下的数目至少一半。
b=b*10+s[j];
}
for(j=(8-i+1)/2+i+1; j<=8; j++){//b取完后剩下的给c
c=c*10+s[j];
}
if(b>c&&b%c==0&&a+b/c==n){
ans++;
}
for(k=(8-i+1)/2+i+1; k<=7; k++){//动态改变b,c
b=b*10+s[k];c=c-s[k]*(int)pow(10, 8-k);
if(b%c==0&&a+b/c==n){
ans++;
}
}
}
}while(next_permutation(s, s+9));
printf("%d", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: