时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
勇士菜哭武获得了一把新的武器,武器有特殊的伤害计算方式。武器的伤害计算方式由若干个部分的和组成,用+号连接。每一部分可以是一个整数a,或者是一个公式ndx。其中a表示固定伤害a点;ndx表示掷n个x面骰子,伤害是所有骰子点数的和。总伤害是每一部分伤害的和。
比如2d6+1d70+3,表示掷两个6面骰子和一个70面骰子(不一定实际存在70面骰子,可以理解成1到70当中随机选择一个整数),再加上固定伤害3点。
他正准备挑选一把好武器,需要计算新武器的伤害期望值,想让你帮他计算一下。
输入描述:
输入一个字符串,表示伤害计算公式。字符串长度不超过5000,对于每一个部分,1≤a, n, x≤1000。a,n,x都是整数。
输出描述:
输出一个数,表示伤害的期望值。如果不是整数,小数点后位数保留最少,即最终结果只有可能是整数或者小数点后是.5的形式,如果不是整数,那么保留一位小数。 示例1
输入
1d6+1d70+1d10+6
输出
50.5
思路:
根据+号分割开,然后分类解决。包含 d 的:n*(x+1)/2;不包含 d 的直接 atoi 一下就可以。
注意避免浮点数运算,可以全部都乘 2 然后输出的时候分奇偶判断是否输出.5。
注意输出浮点数的时候,如果有 1000000 之类的数可能会输出成 1e+06 的形式。全部使用
整数计算可以避免此类问题
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
int main()
{
string s;
cin>>s;
int ans=0;
for(int i=0;i<s.length();i++)
{
string str="";
bool flag1=0;//是否有d
int idx=0;//计数
int idxx=0;//d的下标
for(int j=i;j<=i+8&&j<s.length();j++)
{
if(s[j]=='+') break;
str+=s[j];
if(s[j]=='d')
{
flag1=1;
idxx=idx;
}
idx++;
}
if(!flag1)
{
int num=0;
int mul=1;
for(int j=str.length()-1;j>=0;j--)
{
num+=(str[j]-'0')*mul;
mul*=10;
}
ans+=num*2;
}
else
{
int n=0,x=0;
int mul=1;
for(int j=idxx-1;j>=0;j--)
{
n+=(str[j]-'0')*mul;
mul*=10;
}
mul=1;
for(int j=str.length()-1;j>=idxx+1;j--)
{
x+=((str[j]-'0')*mul);
mul*=10;
}
ans+=(n*(x+1));
}
i+=str.length();
}
cout<<ans/2;
if(ans%2) cout<<".5";
return 0;
}
说实话,题解中处理浮点数的方式是极好的。针对除2的运算,只有整除和余1的情况,那么最后的答案要么是整数,要么余0.5.只要在之前都乘2,判断奇偶,就能知道。
而且题目本身好像也说了如果是整数就不用输出小数形式了。