这天真是考瞎自己了,三道水题,只拿了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;
}
*/