我的位置:首页 > .Net系列>C++

Codeforces 718A Efim and Strange Grade 程序分析

时间:2019-07-23 20:28:00 来源:互联网 作者: 神秘的大神 字体:

Codeforces 718A Efim and Strange Grade 程序分析

jerry的程序

using namespace std;
typedef long long ll;
 
string buf;
int i;
 
void up(int at)
{
    at--;
    if (at < 0)
    {
        buf = '1' + buf;
        i++;
        return;
    }
    if (buf[at] == '.') at--;
    buf[at]++;
    if (buf[at] == '9'+1)
    {
        buf[at] = '0';
        up(at);
    }
}
 
int main()
{
    cin.sync_with_stdio(false); cin.tie(0);
    int n, k;
    cin >> n >> k >> buf;
    while (buf[i] != '.') i++; i++;
    while (i < buf.length() && buf[i] <= '4') i++;
    if (i == buf.length())
    {
        cout << buf << endl;
        return 0;
    }
    for (;buf[i] != '.' && k;i--) if (buf[i] >= '5')
    {
        buf.resize(i); up(i);
        k--;
    }
    if (buf.back() == '.') buf.pop_back();
    cout << buf << endl;
    return 0;
}

首先,先找到小数点第一个后大于等于\(5\)的数位,如果没有的话直接输出原数。

从那个数位起,从后往前循环到小数点处,如果还当前数位大于等于\(5\)且有进位的机会,则先把这个数的结尾改成这个位置,因为之后的所有数都会被清零,然后调用up函数进位,如果有\(9\)的数继续递归,否则退出,如果整数部分首位还要进位,需要在最前面加上\(1\)

最后注意最后一个字符如果是小数点要删去。

总结:用一个函数来执行进位,如果还有进位机会只需继续调用函数就行了,这样处理起来十分方便。

izrak的程序


#include <bits/stdc++.h>
 
#define FO(i,a,b) for (int i = (a); i < (b); i++)
#define sz(v) int(v.size())
 
using namespace std;
 
char s[200005];
 
int main() {
    int l, t;
    scanf("%d %d", &l, &t);
    scanf("%s", s+1);
    s[0] = '0';
    for (int i = 0; i <= l; i++) {
        if (s[i] == '.') {
            for (int j = i+1; j <= l; j++) if (s[j] >= '5') {
                s[j] = 0;
                bool roundup = true;
                t--;
                for (int k = j-1; k > i; k--) {
                    // s[k]++
                    if (roundup) {
                        s[k]++;
                        if (s[k] >= '5' && t) {
                            s[k] = 0;
                            t--;
                            roundup = true;
                        } else roundup = false;
                    }
                }
                if (roundup) {
                    s[i] = 0;
                    for (int k = i-1; k >= 0; k--) {
                        s[k]++;
                        if (s[k] <= '9') break;
                        else s[k] = '0';
                    }
                }
                break;
            }
        }
    }
    if (s[0] != '0') {
        printf("%s\n", s);
    } else {
        printf("%s\n", s+1);
    }
}

这个程序读入时在数字前加上一个前导零,以便处理整数部分首位进位情况。

第一层循环找到小数点的位置,第二层循环找到小数点后第一位大于等于\(5\)的数字,第三层循环(最多进位到小数点),roundup记录是否继续进位,如果进位后还有大于等于\(5\)的数字且还有进位机会,则继续进位。如果第三层循环结束后,仍需继续进位,则在整数部分进位。进位时每进位一次,就把这一位设置为'\0',这样输出时只会输出到第一个'\0'的位置便结束。

注意最后需判断如果开始时加上的前导零仍是零,就不能输出。

总结:用bool变量roundup维护需不需要继续进位,进了位的位置就标为'\0',如果在小数点前面进位直接循环处理即可,这样处理起来不容易错。