问题描述
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
超时代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<sstream>
using namespace std;
int n;
string s="123456789";
int ans;
void s2i(string s,int &num)
{
stringstream ss;
ss<<s;
ss>>num;
}
int main()
{
cin>>n;
int tmp=n;
do{
int a,b,c;
string aa,bb,cc;
for(int i=1;i<=7;i++){ // 第一项的长度
aa = s.substr(0,i);
s2i(aa,a);
if(a>=n) break;
for(int j=i;j<8;j++){ // 第二项的结尾下标
bb = s.substr(i,j-i+1);
s2i(bb,b);
cc = s.substr(j+1);
s2i(cc,c);
int tmp = a + b/c;
if(b%c==0 && tmp==n){
ans++;
}
}
}
}while(next_permutation(s.begin(),s.end()));
cout<<ans<<endl;
return 0;
}
超时分析
s.substr()和s2i函数(字符串转数字)会耗时!
解决方案
- 将字符串转换为字符数组,s.c_str()函数实现(替代s.substr())
- 写一个parse函数实现分割字符数组求数值(替代s2i函数)
满分代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
int N;
int parse(const char* str,int pos,int len)
{
int num=0;
for(int i=pos;i<=pos+len-1;i++){
num *= 10;
num += (str[i]-'0');
}
return num;
}
int main()
{
int ans=0;
cin>>N;
string s = "123456789";
do{
const char* str = s.c_str(); // string 转换为 (const)char*
for(int i=1;i<=7;i++){ // +的位置
int inta = parse(str,0,i); // 从0开始的第i个,不包括 i
if(inta>=N) break; // 放弃 inta的继续探索(及时终止不必要的循环)
for(int j=1;j<9-i;j++){ // j第二个数的长度
int intb = parse(str,i,j);
int intc = parse(str,i+j,9-i-j); // N-i-j第三个数的长度
if(intb%intc==0 && inta+intb/intc==N) ans++;
}
}
}while(next_permutation(s.begin(),s.end())); // string用 begin() 和 end()
cout<<ans<<endl;
return 0;
}