模拟赛记录(2):10.31 T1 double精度问题,T2 Trie树

这天真是考瞎自己了,三道水题,只拿了180分。真是值得注意~.~。

T1:给定n,s和数列a,表示数列a有n个整数,每个数不超过s,求平均数,保留12位小数输出。

并没有注意过double的精度误差有多大,于是也没想别的就直接用double储存,直接算。最后是A4个,W5个,T1个。精度误差导致W,而T的原因,应该是浮点数的运算比整形要慢,所以复杂度上自带常数。在自己的CPU上跑了一下,1亿次整形加/乘只需要200ms,整形除法是300ms,而1亿次浮点型除法是450ms。
这道题处理精度误差的方法就是把小数和整数部分分开算,分开输出,根据数据范围,unsigned long long是可以满足需求的。输出时有个小技巧”%llu.%012llu”,%012llu是输出占12个字符位置,数本身不满12位前面补零。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long UL;

UL n, s, x, a, ans;

int main()
{
    scanf("%llu %llu", &n, &s);
    for(int i = 1; i <= n; i++)
    {
        scanf("%llu", &a);
        ans += a/n, x += a%n;
        if(x >= n) ans += x/n, x %= n;
    }   
    x = (x*(UL)10000000000000/n+(UL)5)/(UL)10;
    printf("%llu.%012llu", ans, x);
    return 0;
}

T2:
这里写图片描述

当时我绞尽脑汁也没想出来什么好的做法,最后无奈地写了个DP+KMP拿了40分的暴力分。全然没想到只需要建一棵Trie树再贪心就可以。Trie树还没写过,基本快忘掉了,如果不是这次模拟赛,可能NOIP考场上我也想不到用Trie树解决问题。【严重知识漏洞】
然而这题也不能裸跑Trie树,会爆内存,需要用set压缩空间。时间复杂度,O(m^3)把每一个B串(长度<=200)的每一个后缀都加到Trie中,之后O(n)跑贪心。

//然而十分日狗的是,我满怀希望的写完了set压缩空间的版本,跑T了9个点。原本不压缩空间,也就是跑MLT4个点罢了。。是我YY的set不对么。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#define road first
#define id second
using namespace std;
typedef pair<int,int> PII;
typedef set<PII>::iterator Setit;

int id(char c)
{
    if(c <= 'z' && c >= 'a') return c-'a'+1;
    if(c <= 'Z' && c >= 'A') return c-'A'+27;
    if(c <= '9' && c >= '0') return c-'0'+53;
    if(c == '_') return 63; if(c == '@') return 64;
    return 0;
}

struct Node
{
    set <PII> Set;
    Node(){Set.clear();}    
};

struct Trie
{
    vector <Node> Tree;
    Trie()
    {
        Tree.clear();
        Node t; Tree.push_back(t); 
    }
    void add(int now, char *s)
    {
        int t = id(s[1]), num;
        if(!t) return ;
        Setit it = Tree[now].Set.lower_bound(make_pair(t, 0));
        if((*it).road != t)
        {
            Node nxt; Tree.push_back(nxt);
            num = Tree.size()-1;
            Tree[now].Set.insert(make_pair(t, num)); 
        }
        else num = (*it).id;
        add(num, s+1);
    }
    int query(int now, char *s)
    {
        int t = id(s[1]), num; if(!t) return 0;
        Setit it = Tree[now].Set.lower_bound(make_pair(t, 0));
        if((*it).road != t) return 0; else num = (*it).id;
        return query(num, s+1) + 1;
    }
};

int n; char A[1000005], B[205];
Trie T;

int main()
{
    freopen("editor.in", "r", stdin);
    freopen("editor.out", "w", stdout);
    scanf("%s %d", A+1, &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", B+1);
        int m = strlen(B+1);
        for(int j = 0; j < m; j++) T.add(0, B+j);
    }

    int cnt = 0, pos = 0, t; n = strlen(A+1);
    while((t = T.query(0, A+pos)) && pos <= n) cnt++, pos += t;

    if(pos == n) printf("%d", cnt);
    else printf("QAQ");
    return 0;
}
/*
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

int id(char c)
{
    if(c <= 'z' && c >= 'a') return c-'a'+1;
    if(c <= 'Z' && c >= 'A') return c-'A'+27;
    if(c <= '9' && c >= '0') return c-'0'+53;
    if(c == '_') return 63; if(c == '@') return 64;
    return 0;
}

struct Node
{
    int nx[65];
    Node(){memset(nx, 0, sizeof nx);}   
};

struct Trie
{
    vector <Node> Tree;
    Trie()
    {
        Tree.clear();
        Node t; Tree.push_back(t); 
    }
    void add(int now, char *s)
    {
        int t = id(s[1]);
        if(!t) return ;
        if(!Tree[now].nx[t])
        {
            Node nxt; Tree.push_back(nxt);
            Tree[now].nx[t] = Tree.size()-1; 
        }
        add(Tree[now].nx[t], s+1);
    }
    int query(int now, char *s)
    {
        int t = id(s[1]);
        if(!t || !Tree[now].nx[t]) return 0;
        int res = query(Tree[now].nx[t], s+1);
        return res + 1;
    }
};

int n; char A[1000005], B[205];
Trie T;

int main()
{
    scanf("%s %d", A+1, &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", B+1);
        int m = strlen(B+1);
        for(int j = 0; j < m; j++) T.add(0, B+j);
    }

    int cnt = 0, pos = 0, t; n = strlen(A+1);
    while((t = T.query(0, A+pos)) && pos <= n) cnt++, pos += t;

    if(pos == n) printf("%d", cnt);
    else printf("QAQ");
    return 0;
}
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值