集训Day 2
A题:
B题:
比赛开始先整了第一题,由于题面很高级一看就是我写不出正解的样子,就先写了一个暴力,然后开始考虑如何优化,突然开窍啦~前缀和!然后瞎优化了一番,总算过了所有样例(get100points),第二题吗…………看了半天重构了3次思路,还是连样例1都爆零。然后就放弃了好一点的解法选择了暴力,高兴的写出了暴力,但是,不出意外的话就要出意外了,最后要交程序的时候我如弱智一般,将怕过不去数据全heck了一遍,本来60pt的程序被我改成了0pt,为什么呢?输入的n判断的i,最后由于程序判断i未定义,原地升天。
TIPS: 1. 考试注意文件名以及一定要测过了样例,没测样例基本 0 分(交上来编译错误更是不可接受) 2. 可以自己尝试写 generator.cpp 来造数据,需要使用 srand(time(0)) 和 rand() 函数(问题:如何得到 [l, r] 内的一个整数)? 3. 可以多写个暴力来跑自己造出来的数据 4. 浮点数由尾数和阶码构成 5. 中缀表达式转后缀表达式 6. 已知前序遍历和后序遍历,一般无法得到确定的中序遍历,但是可以从选项使用排除法 7. 一个愚蠢的记正负整数的办法是将第一位作为符号位,剩下的记录数字,这样的话记录范围是 [-127, 127](八位,少一个是因为 0 和 -0 不同 ),且这样很难搞加法 8. 考虑采用补码记录整数,-x = ~x + 1,让 x 和 -x 相加时自然溢出从而得到 0,这样能记录的范围是 [-128, 127],且最高位仍然是符号位
B题:
设f[i][j]表示首位是i,结尾是j的数字的个数,那么,符合条件的数字必然被f[i][j]或f[j][i]统计,所以只需要将[1,n]中的数字统计进入f数组,接下来枚举i,j同时计算答案即可。
A题程序:
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; long long n,l,r,a[N],sum[N],maxn=-100; int main() { ios::sync_with_stdio(false); freopen( "times.in", "r", stdin ); freopen( "times.out", "w", stdout ); cin>>n>>l>>r; for(int i=1;i<=n;i++) cin>>a[i]; sum[1]=a[1]; for(int i=2;i<=n;i++) sum[i]=sum[i-1]+a[i]; for(int i=1;i<=n;i++) { long long start=max((long long)i-l,(long long)1),end=min(n,(long long)i+r); maxn=max(maxn,(sum[i]-sum[start-1])*(sum[end]-sum[i-1])); } for(int i=1;i<=n;i++) { long long start=max((long long)i-l,(long long)1),end=min(n,(long long)i+r); if((sum[i]-sum[start-1])*(sum[end]-sum[i-1])==maxn) printf("%d ",i); } return 0; }
B题程序:
#include<bits/stdc++.h> using namespace std; int f[114][514]; void s114514_1919810(int i) { string s=to_string(i); f[s[0]-'0'][s.back()-'0']++; } long long c1145141919810(int n) { for(int i=0;i<10;i++) for(int j=0;j<10;j++) f[i][j]=0; for(int i=1;i<=n;i++) s114514_1919810(i); long long res=0; for(int i=0;i<10;i++) for(int j=0;j<10;j++) res+=(long long)f[i][j]*f[j][i]; return res; } int main() { ios::sync_with_stdio(false); int n114514_1919810; cin>>n114514_1919810; cout<<c1145141919810(n114514_1919810); return 0; }