题意 : 输入正整数n,按从小到大的顺序输出所有形如abcde/fghij = n的表达式,其中a~j恰好为数字0~9的一个排列(可以有前导0),2≤n≤79。
分析 : 最暴力的方法莫过于采用数组存储0~9然后next_permutation枚举排列再带入表达式看是否满足等式,但是这样的复杂度就是O(10!)了,时间复杂度超高。所以采取另外一种枚举方法,先枚举分母fghij,再根据分母算出分子,然后检测分母分子出现的字数是否有重复即可。那这样的复杂度是多少呢?复杂度主要就在枚举分母上了,枚举分母的方法就是采用一个for(int Flood=1234; Flood<100000; Flood++); ,枚举量大大减少。
O(10!)
#include<bits/stdc++.h> using namespace std; int main(void) { int n; int digit[10] = {0,1,2,3,4,5,6,7,8,9}; int blank = 0; while(~scanf("%d", &n) && n){ if(blank++) puts(""); bool Have = false; do{ int Ceil = digit[0]*10000 + digit[1]*1000 + digit[2]*100 + digit[3]*10 + digit[4]; int Flood = digit[5]*10000 + digit[6]*1000 + digit[7]*100 + digit[8]*10 + digit[9]; if(n * Flood == Ceil) {printf("%d%d%d%d%d / %d%d%d%d%d = %d ",digit[0],digit[1],digit[2],digit[3],digit[4],digit[5],digit[6],digit[7],digit[8],digit[9],n);Have=true;} }while(next_permutation(digit, digit+10)); if(!Have) printf("There are no solutions for %d. ", n); } return 0; }
O(AC)
#include<bits/stdc++.h> using namespace std; bool check(int Ceil, int Flood) { bool digit[10]; for(int i=0; i<10; i++) digit[i] = false; if(Ceil<10000) digit[0] = true; while(Ceil){ int remainder = Ceil%10; if(digit[remainder]) return false; else digit[remainder] = true; Ceil/=10; } if(Flood<10000){ if(digit[0]) return false; else digit[0] = true; } while(Flood){ int remainder = Flood%10; if(digit[remainder]) return false; else digit[remainder] = true; Flood/=10; } return true; } int main(void) { int n; int blank = 0; // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); while(~scanf("%d", &n) && n){ if(blank++) puts(""); bool Have = false; for(int Flood=1234; Flood<100000; Flood++){ int Ceil = Flood * n; if(Ceil > 99999) continue; else{ if(check(Ceil, Flood)){ Have = true; if(Ceil<10000) putchar('0'); printf("%d / ", Ceil); if(Flood<10000) putchar('0'); printf("%d = %d ", Flood, n); } } } if(!Have) printf("There are no solutions for %d. ", n); } return 0; }