jzoj 模拟赛总结(2017.07.13)
来源:互联网 发布:网络爬虫软件下载 编辑:程序博客网 时间:2024/06/08 18:43
T1.
马农:
题目大意:
来自大草原的两兄弟决心成为超级“马农”,专门饲养战马。他们将可以养马的区域,分为 N*N 的单位面积的正方形,每块单位面积的收益为a[i,j],收益a[i,j]可能是负数,养马也不是包赚的,马匹也可能出现生病死亡等意外。然后两人的马场都必须是矩形区域。同时,规定两个马场的矩形区域相邻,且只有一个交点。且两人希望两个马场的收益相当,希望你给他们设计马场,求共有多少种设计方案。
40%的数据, N<=10。
100%的数据, N<=50, -1000 < A(i,j)<1000
题解:
枚举每一个点为交点的情况,然后分成四部分:
左上部分,右上部分,左下部分,右下部分
然后枚举左上部分的全部可能出现的数塞进hash表中,并记录出现次数,
然后枚举其对应的右下部分出现的全部可能,然后在hash表中找。
右上,左下部分同理
不过要注意hash表的清空,每次找到一个数,要把这个数的hash表位置记录,然后清零的时候就不用清全部hash表,只需要清空使用过的位置,就可以达到优化,避免潮湿。
当然,这题数据小,开个大数组做桶去记录也可以水掉。
const modn=300007;var hash:array [0..modn,1..2] of longint; p:array [0..modn] of longint; sum:array [0..51,0..51] of longint; n,i,j,k,l,m,cd,ans:longint;function insert(d:longint):longint;var i:longint;begin i:=abs(d) mod modn; while (hash[i,1]<>0) and (hash[i,1]<>d) do begin inc(i); if i>modn then i:=0; end; exit(i);end;begin assign(input,'farmer.in'); reset(input); assign(output,'farmer.out'); rewrite(output); readln(n); for i:=1 to n do begin for j:=1 to n do begin read(sum[i,j]); sum[i,j]:=sum[i,j-1]+sum[i,j]; end; readln; end; for i:=1 to n do for j:=1 to n do begin p[0]:=0; for k:=0 to j-1 do begin l:=0; for m:=i downto 1 do begin l:=l+(sum[m,j]-sum[m,k]); inc(p[0]); p[p[0]]:=insert(l); hash[p[p[0]],1]:=l; inc(hash[p[p[0]],2]); end; end; for k:=j+1 to n do begin l:=0; for m:=i+1 to n do begin l:=l+(sum[m,k]-sum[m,j]); cd:=insert(l); if hash[cd,1]=l then inc(ans,hash[cd,2]); end; end; for k:=1 to p[0] do begin hash[p[k],1]:=0; hash[p[k],2]:=0; end; p[0]:=0; for k:=j to n do begin l:=0; for m:=i downto 1 do begin l:=l+(sum[m,k]-sum[m,j-1]); inc(p[0]); p[p[0]]:=insert(l); hash[p[p[0]],1]:=l; inc(hash[p[p[0]],2]); end; end; for k:=0 to j-2 do begin l:=0; for m:=i+1 to n do begin l:=l+(sum[m,j-1]-sum[m,k]); cd:=insert(l); if hash[cd,1]=l then inc(ans,hash[cd,2]); end; end; for k:=1 to p[0] do begin hash[p[k],1]:=0; hash[p[k],2]:=0; end; end; writeln(ans); close(input); close(output);end.
T2.
马语翻译:
有N个马种,机器人有 M 种,每种机器人能完成 K 个马种之间的语言翻译。问,利用这些机器人,能否实现 1 种群和 N 种群的马语翻译。 若可以,找到翻译过程至少需要用到多少种语言,求最少转换语言的次数。如果无法完成翻译,输出-1。
40%的数据 N<=100, 1<=K<=20, M<=40。
100%的数据 1<=N<=100000, 1<=K<=1000, 1<=M<=1000
题解:
有待完成。。。
T3.
马球比赛:
N个乡镇之间要进行马球联赛。每个乡镇有a[i]匹马,首先,所有乡镇都要求,本乡镇所有的马匹都必须参赛,或者都不参赛(若组队的马匹数量不是该镇马匹数量的约数,将无法参赛)。其次,在本乡镇,选出最佳球队,参加乡镇间联赛。比赛组织方希望满足所有参赛乡镇的要求,并且使得决赛的马匹尽可能多,请你设计每个球队马匹的数量,使得决赛马匹数最大。
注意,决赛至少有 2 个队伍晋级。
20%的数据 2<=N<=100, 1<=a(i)<=10000。
50%的数据 2<=N<=20000。
100%的数据 2<=N<=200000, 1<=a(i)<= 2000000
题解:
这题呢,其实可以递推
首先设f[i]表示以i为参赛标准时,有多少只队伍能参赛。
可以推出:
f[j]=f[j]+f[i] j为i的约数
同理,f[i div j]=f[i div j]+f[i] 然后容易被卡常,就自行脑补
时间复杂度:O(max(a[i])*Σtrunc(sqrt(i)))
//i为1~max(a[i])
var sum:array [0..2000001] of int64; a:array [0..200001] of longint; cmax,p,q,n,i,j:longint; mmax:int64;function max(aa,bb:int64):int64;begin if aa>bb then exit(aa); exit(bb);end;begin assign(input,'polo.in'); reset(input); assign(output,'polo.out');rewrite(output); read(n); cmax:=0; for i:=1 to n do begin read(a[i]); inc(sum[a[i]]); cmax:=max(cmax,a[i]); end; mmax:=n; if cmax=2000000 then cmax:=cmax div 20; for i:=2 to cmax do if sum[i]<>0 then begin for j:=2 to trunc(sqrt(i)) do if (i mod j=0) then begin sum[j]:=sum[j]+sum[i]; if j*j<>i then sum[i div j]:=sum[i div j]+sum[i]; end; end; if cmax=100000 then cmax:=cmax*20; for i:=2 to cmax do if sum[i]>1 then mmax:=max(mmax,sum[i]*i); writeln(mmax); close(input); close(output);end.
T4.
数列:
题目大意:
给定一个长度为N的数列,求一段连续的子数列满足该子数列中的各元素的平均数大于A,输出可行方案的总数。
对于60%的数据 N <= 1000
对于100%的数据 N <= 100000
所有数据包括都在longint范围内。
题解:
其实对于每一次的输入的数a[i],我们都将它减去平均数A,然后全部做一遍前缀和。
首先我们知道对于某个前缀和sum[i],如果它>0就先给答案+1
然后如果sum[i] < sum[j],i < j就代表在区间[l,r]内的总和是绝对比A大的,就累加1
然后我们怎么去处理sum[j]>sum[i]的情况呢,我们发现如果强行去枚举
时间复杂度就是O(Σ N),很明显会炸时间
然后我们可以想到树状数组,
先将处理出来的sum全部离散,因为离散后其的大小关系如sum[i] < sum[j]是不变的,然后离散后其的最坏情况最大值就是N,即100000,树状数组就只需要开到100000了,
然后枚举sum,
每次对于一个sum[i]
ans累加其树状数组中1~i-1的值,用x-x and (-x)去递减
然后将这个数丢进树状内
用x+x and (-x)去 递进,tree[x]=tree[x]+1
然后这样的时间复杂度就做到了O(N log N)
var d,rp,sum:array [0..100001] of longint; x,i,j,n,m,pd:longint; ans:int64;procedure qsort(l,r:longint);var mid,i,j:longint;begin if l>=r then exit; i:=l; j:=r; mid:=sum[(l+r) div 2]; repeat while sum[i]<mid do inc(i); while sum[j]>mid do dec(j); if i<=j then begin sum[0]:=sum[i]; d[0]:=d[i]; sum[i]:=sum[j]; d[i]:=d[j]; sum[j]:=sum[0]; d[j]:=d[0]; inc(i); dec(j); end; until i>j; qsort(i,r); qsort(l,j);end;begin assign(input,'sequence.in'); reset(input); assign(output,'sequence.out'); rewrite(output); readln(n,m); ans:=0; for i:=1 to n do begin read(x); sum[i]:=sum[i-1]+(x-m); if sum[i]>0 then inc(ans); d[i]:=i; end; qsort(1,n); i:=1; j:=1; while i<=n do begin rp[d[i]]:=j; while sum[i]=sum[i+1] do begin inc(i); rp[d[i]]:=j; end; inc(i); inc(j); end; dec(j); for i:=0 to j do sum[i]:=0; for i:=1 to n do begin pd:=rp[i]-1; while pd>0 do begin ans:=ans+sum[pd]; pd:=pd-pd and (-pd); end; pd:=rp[i]; while pd<=j do begin sum[pd]:=sum[pd]+1; pd:=pd+pd and (-pd); end; end; writeln(ans); close(input); close(output);end.
- jzoj 模拟赛总结(2017.07.13)
- jzoj 模拟赛总结(2017.07.08)
- jzoj 模拟赛总结(2017.07.09)
- jzoj 模拟赛总结(2017.07.10)
- jzoj 模拟赛总结(2017.07.11)
- jzoj 模拟赛总结(2017.07.12)
- jzoj 模拟赛总结(2017.07.14)
- jzoj 模拟赛总结(2017.07.15)
- [暑假集训] jzoj 2016.7.13 noip模拟赛B 总结
- [暑假集训] jzoj 2016.8.13 noip模拟赛B 总结
- 【集训】jzoj 2017.7.13 noip模拟赛A 总结
- jzoj 2016.11.27 gdkoi模拟赛 总结
- 【集训】jzoj 2017.7.5 noip模拟赛A 总结 (欧拉回路)
- jzoj 2016.5.14noip模拟赛C 总结
- jzoj 2016.5.21noip模拟赛C 总结
- jzoj 2016.5.28noip模拟赛C 总结
- jzoj 2016.6.11noip模拟赛B总结
- jzoj 2016.6.25noip模拟赛C 总结
- FZU2254 英语考试(最小生成树,Prim)(福州大学第十四届程序设计竞赛)
- 关于sampling softmax 中重要性采样的论文阅读笔记
- HDU 1325 Is It A Tree?
- OpenCV 2.4.9+vs2013的配置
- C++排序算法
- jzoj 模拟赛总结(2017.07.13)
- Android Studio技巧
- 基础
- 《剑指offer》两个链表的第一个公共节点
- 增加数组的维度
- Sublime Text 新建文件的模版插件: SublimeTmpl
- 过滤器(Filter)和监听器(Listener)
- JSON怎么转成Excel
- BZOJ 2006: [NOI2010]超级钢琴