历届试题 带分数  
时间限制: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
 
思路:标的分类有时候会误导人。使用什么方法还是要有自己的判断,不能光靠提示往那方面去想。
受到分类的影响用枚举,可以过三个测试数据,但是1000000以内的有些数可能会超时,这里的枚举不是毫无技巧地枚举而是全排列后再枚举。
更好的方法可以用全排列1-9,然后按顺序分成三个数,再判断是否可以满足条件。
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#define FOR(i,x,n) for(long i=x;i<n;i++)
#define ll long long int
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define MAX_N 50005

using namespace std;

int a[11];
int cou=0;

bool check(){
    if(a[0]>0){
        return false;
    }
    FOR(i,1,10){
        if(a[i]>1||a[i]==0){
            return false;
        }
    }
    return true;
}

void record(int aa){
    while(aa){
        int t=aa%10;
        a[t]++;
        aa/=10;
    }
}

bool jud(int aa){
    int b[11]={0};
    while(aa){
        int t=aa%10;
        b[t]++;
        if(b[t]>1){
            return false;
        }
        aa/=10;
    }
    return true;
}

int main()
{
    //freopen("data.txt", "r", stdin);
    //freopen("data.out", "w", stdout);
    long n;
    scanf("%d",&n);
    cou=0;
    FOR(i,1,n){
        if(jud(i)){
                FOR(j,1,5000){
                    if(jud(j)){
                        fill(a,a+11,0);
                        record(i);
                        record(j);
                        int t=j*n-i*j;
                        record(t);
                        if(check()){
                            cou++;
                        }
                    }
                }
        }
    }
    printf("%d\n",cou);
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}