2019.7.7 校内测试题 分数化小数

 题目

  分数化小数(fracdec.cpp,128MB,1s)

【问题描述】:

  写一个程序,输入一个形如 N/D 的分数(N 是分子,D 是分母),输出它的
小数形式。如果小数有循环节的话,把循环节放在一对括号中。例如:
1/3=0.33333… 写成 0.(3);41/333=0.123123123… 写成 0.(123)。
用*.0 表示整数,如 2/2=1.0

【输入文件】:

   单独的一行包括被空格隔开的 N 和 D。(1≤N、D≤100000)

【输出文件】:

  输出一行,即分数 N/D 的小数形式。

【输入输出样例】:

  
  样例 1:
    fracdec.in
      45 46
    fracdec.out
      0.803(571428)
  样例 2:
    fracdec.in
      3 8
    fracdec.out
      0.375
  样例 3:
    fracdec.in
      8 4
    fracdec.out
      4.0

【数据规模】:

  如上

 

 

考试得分:  60

 

 

主要算法 :  除法(循环节性质)

 

 

 

题干:

    分数化为小数

 

 

应试策略:

  1.现将小数点前的lead求出,特殊处理没有小数点后的情况

  2.再将整除的特殊处理
  3.剩下的用KMP进行枚举

   代码

 

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)
#define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout)

using namespace std;
const int N=100;
int a,b,lead,cnt;
string s="";
bool Check(string ss,int sp)
{
    int len=ss.size();
    FORa(k,1,6)
    {
        FORa(i,1,len) if(ss[i-1]!=s[sp+len+i-1]) return 0;    
        sp=sp+len;
    }    
}
void Init()
{
    scanf("%d%d",&a,&b);
    lead=a/b,a=a%b,a*=10;
    if(!a) {printf("%d.0",lead);return;}
    while(a&&cnt<=500) s=s+char(a/b+'0'),a=(a%b)*10,cnt++;
    if(!a) {printf("%d.",lead),cout<<s;return;    }
    int len=s.size()-1;
    FORa(i,0,len)
        FORa(j,i,len)
        {
            string fs;int sp;
            fs.clear();
            FORa(k,i,j) fs=fs+s[k];
            sp=s.find(fs,i);
            if(Check(fs,sp))
            {
                printf("%d.",lead);
                FORa(i,0,sp-1) printf("%c",s[i]);
                printf("("),cout<<fs,printf(")");
                return;
            }
        }
    cout<<s;
}
int main()
{
    File("fracdec");
    Init();
    return 0;
}

 

 

 

 

 

 

非完美算法:  

    照搬应试策略

 

 

正解:

    初等数学(循环节的基本性质),知道循环节的出现为除数再次出现

  代码

   

#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)
#define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout)

using namespace std;
const int N=100;
int a,b,lead,cnt;
string s="";
map<int,int> mp;
void Init()
{
    scanf("%d%d",&a,&b);
    lead=a/b,a=a%b,a*=10,mp[a]=++cnt;
    if(!a) {printf("%d.0",lead);return;}
    while(a) 
    {
        s=s+char(a/b+'0'),a=(a%b)*10,++cnt;
        if(mp[a])
        {
            printf("%d.",lead);
            for(int i=0;i<mp[a]-1;i++) printf("%c",s[i]);
            printf("(");
            FORa(i,mp[a]-1,cnt-2) printf("%c",s[i]);
            printf(")");
            return;
        }
        mp[a]=cnt;
    }
    printf("%d.",lead);
    cout<<s;
}
int main()
{
    File("fracdec");
    Init();
    return 0;
}

 

 

 

 

总结:

  知道循环节的出现为除数再次出现

 

 

 

 

 

 

posted @ 2019-07-11 20:50  SeanOcean  阅读(539)  评论(0编辑  收藏  举报