Map查重-循环小数

 

原题摘录:循环小数(Repeating Decimals,ACM/ICPC World Finals 1990,UVa202)

输入整数a[0,3000]和b[1,3000],输出a/b的循环小数以及其循环节长度.例如a=5,b=43,小数表示为0.(116279069767441860465),循环节长度为21.

本题实际上是模拟长除法的计算过程,其中每一次除法时都有被除数和余数,当被除数出现重复就表示出现循环节了.所以要记录每一次的被除数及其在循环小数中的位置<是否已经想到键值对>,需要注意,当被除数不够除时,每一次补零也需要记录及其对应的位置.

1.在Map初始状态时所有值均为0.每当有一个被除数作为键存进去后,值就++(通过增加答案长度的同时达到此目的,一石二鸟),当下一个被除数进来时,如果相同,那么他就已经有对应的值.达到检查是否重复的目的.

2.小数位通过记录每次对应的新的余数*10/const被除数,然后转化为字符添加到ans中去.新的余数=旧的余数*10%const被除数

完整代码:

说明:string.insert(index,"string").在index位置插入字符串string

还有一个典型例子是:反片语(Ananagram,UVa 156)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
const int maxn=3000 + 10;
map<int,int> Pos;

void solve(int n,const int d,string& ans,int& r)
{
    assert(n%d&&n<d);//不能整除且余数小于被除数 
    
    ans=".";
	Pos.clear();
	
	while(true){
		n*=10;
		int p=Pos[n];
		if(p==0) Pos[n]=ans.size();
		else{
			r=ans.size()-p;
			if(r>50) {ans.erase(p+50);ans+="...";}
			ans.insert(p,"(");
			ans+=")";
			break;
		}
		if(n<d) {ans+='0';continue;}//补0
		int div=n/d,mod=n%d;
		ans+=(char)(div+'0');
		n=mod;
		if(n==0) {ans+="(0)";r=-1;break;	} 
	} 
}

int main(int argc, char** argv)
{
	int a,b;
	while(cin>>a>>b){
	string ans="0.(0)";//赋值对答案无影响,标记出答案的样式,后面会进行修改 
	int r=1;
	if(a%b)
	solve(a%b,b,ans,r);//四个参数:余数,被除数,循环小数,循环节长度 例5/43=0.(116279069767441860465) 21 
	
    cout<<a<<"/"<<b<<"="<<a/b<<ans<<endl;
    cout<<"repeating cycle number:"<<r<<endl;
	cout<<endl;	
	}
   
	return 0;
}

附:注意标题,是查重,不是去重(set)

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值