学大伟业Day解题报告
预计分数:30+30+0=60
实际分数:30+20+0=50
题解部分全部来自http://www.cnblogs.com/TheRoadToTheGold/p/7723564.html
T1https://www.luogu.org/problem/show?pid=T14734
不会。。打30分暴力走人
对于60%的分数
通过观察可知设当前坐标为x,则通过坐标为a的圆环可移动到2a-x处。连续通过两个圆环(a,b)可以移动到x+(2b-2a)处。
先以移动步数为偶数情况考虑简化版问题:设圆环坐标为a[1]~a[n],对于任意两个圆环,可由坐标x变为x+2(a[j]-a[i]),题目转化为对于N^2个数其中b[i,j]=2(a[j]-a[i]),通过有限次加减运算能否由x=0变化至目标。
根据广义裴蜀定理以及扩展欧几里得相关原理可知,当且仅当目标为gcd的倍数时有解。故预处理出全部可能的2(a[j]-a[i]),求出其最大公约数,在判断目标是否为gcd的倍数即可。
对于奇数的情况,可以通过枚举第一步的方案转化为偶数的情况,即维护一个set表示0步或1步可达点集(mod gcd意义下),再查询目标点在mod gcd下是否属于这个集合即可。复杂度瓶颈在于N^2个数求gcd。
对于100%的分数
通过欧几里得算法的性质与更相减损术可知gcd(a,b)=gcd(a-b,b)。设p1={2*(a[i]-a[1])|i>1}的最大公约数,设p2={2*(a[i]-a[j])}的最大公约数,易知p1>=p2(因为p1比p2约束宽松)。而对于任意i,j由于p1同时是2*(a[i]-a[1])、2*(a[j]-a[1])的约束,那么p1也一定是任意2*(a[i]-a[1])-2*(a[j]-a[1])=2*(a[i]-a[j])的约数,故p1<=p2。综上所述p1=p2,这样就不需要N^2个数同时求gcd了,只求p1即可,可获得满分。
1 #include<set> 2 #include<cstdio> 3 #include<iostream> 4 #include<algorithm> 5 6 using namespace std; 7 8 typedef long long LL; 9 10 #define N 100001 11 12 LL a[N]; 13 14 set<LL>S; 15 16 void read(LL &x) 17 { 18 x=0; int f=1; char c=getchar(); 19 while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } 20 while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } 21 x*=f; 22 } 23 24 LL getgcd(LL i,LL j) { return !j ? i : getgcd(j,i%j); } 25 26 int main() 27 { 28 freopen("ninja.in","r",stdin); 29 freopen("ninja.out","w",stdout); 30 int n,m; 31 scanf("%d%d",&n,&m); 32 for(int i=1;i<=n;i++) read(a[i]); 33 LL gcd=0; 34 for(int i=2;i<=n;i++) gcd=getgcd(abs(a[i]-a[1]<<1),gcd); 35 LL x; 36 if(gcd) 37 { 38 S.insert(0); 39 for(int i=1;i<=n;i++) S.insert((2*a[i]%gcd+gcd)%gcd); 40 while(m--) 41 { 42 read(x); 43 puts(S.find((x%gcd+gcd)%gcd)!=S.end() ? "Yes" : "No"); 44 } 45 } 46 else 47 { 48 while(m--) 49 { 50 read(x); 51 puts(x==a[1]*2 ? "Yes" : "No"); 52 } 53 } 54 }
T2https://www.luogu.org/problem/show?pid=T14735
有20分裸地暴力
还有10分裸的线段树
其他的不会做,,后来线段树写炸了QWQ、、、
线段树
先下放取反标记,在下方加标记
下放取反标记时,若存在加标记,加标记也取反
关键是如何处理加标记的影响
设当前线段树区间有4个数x1,x2,x3,x4
sum[i] 表示 选出i个数的乘积 的和
sum[1]=x1+x2+x3+x4
sum[2]=x1x2+x1x3+x1x4+x2x3+x2x4+x3x4
sum[3]=x1x2x3+x1x2x4+x1x3x4+x2x3x4
sum[4]=x1x2x3x4
操作:区间加a
以sum[3]为例
新的sum[3]=
(x1+a)(x2+a)(x3+a) +
(x1+a)(x2+a)(x4+a) +
(x1+a)(x3+a)(x4+a) +
(x2+a)(x3+a)(x4+a)
=x1x2x3+a(x1x2+x1x3+x2x3)+a^2(x1+x2+x3)+a^3 +
x1x2x4+a(x1x2+x1x4+x2x4)+a^2(x1+x2+x4)+a^3 +
x1x3x4+a(x1x3+x1x4+x3x4)+a^2(x1+x3+x4)+a^3 +
x2x3x4+a(x2x3+x2x4+x3x4)+a^2(x2+x3+x4)+a^3
=sum[3] + a*sum[2]*2 + a^2*sum[1]*3 + a^4
所以 对有siz个元素的区间执行区间加a操作
那么sum[]的更新:
for i: 10 ——> 1
for j:i-1——>1
sum[i]+=a^(i-j)*sum[j]*C(siz-j,i-j)
解释:
有i个(xi+a)相乘
从里面选出j个xi,那就只能选i-j个a
后面那个组合数?
一共有siz个(xi+a) ,已经确定了有j个(xi+a)选择xi
一共要选i个(xi+a),那就要从剩下的siz-j个(xi+a)里选出 i-j个(xi+a)来用他们的a
所以是C(siz-j,i-j)
区间的合并
枚举左边选j个,那右边就选i-j个,乘起来就行了
例:
假设当前要选3个数
左边有2个数x1,x2 选1个,
右边有3个数x3,x4,x5 选2个
那就是 x1*x3*x4+x1*x3*x5+x1*x4*x5+x2*x3*x4+x2*x3*x5+x2*x4*x5
=x1*右边的sum[2]+x2*右边的sum[2]
=左边的sum[1] * 右边的sum[2]
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 5 using namespace std; 6 7 #define N 50001 8 9 const int mod=1e9+7; 10 11 typedef long long LL; 12 13 int n; 14 15 int C[N][11]; 16 17 int f[N<<2]; 18 int siz[N<<2],mid[N<<2]; 19 bool rev[N<<2]; 20 21 struct node { int sum[11]; }ans[N<<2]; 22 23 void read(int &x) 24 { 25 x=0; int ff=1; char c=getchar(); 26 while(!isdigit(c)) { if(c=='-') ff=-1; c=getchar(); } 27 while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } 28 x*=ff; 29 } 30 31 int tot=0; 32 33 void MOD(int &a,int b) 34 { 35 a+=b; 36 a-= a>=mod ? mod : 0; 37 } 38 39 void pre(int n) 40 { 41 C[0][0]=1; 42 for(int i=1;i<=n;i++) 43 { 44 C[i][0]=1; 45 for(int j=1;j<=min(i,10);j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; 46 } 47 } 48 49 void update(int k) 50 { 51 for(int i=1;i<=10;i++) 52 { 53 ans[k].sum[i]=0; 54 for(int j=1;j<i;j++) MOD(ans[k].sum[i],1ll*ans[k<<1].sum[j]*ans[k<<1|1].sum[i-j]%mod); 55 MOD(ans[k].sum[i],ans[k<<1].sum[i]); MOD(ans[k].sum[i],ans[k<<1|1].sum[i]); 56 } 57 } 58 59 void build(int k,int l,int r) 60 { 61 siz[k]=r-l+1; 62 if(l==r) { read(ans[k].sum[1]); MOD(ans[k].sum[1],0); return; } 63 mid[k]=l+r>>1; 64 build(k<<1,l,mid[k]); build(k<<1|1,mid[k]+1,r); 65 update(k); 66 } 67 68 void insert(int k,int w) 69 { 70 MOD(f[k],w); 71 for(int i=10;i;i--) 72 { 73 int x=w; 74 for(int j=i-1;j;j--,x=1ll*x*w%mod) 75 MOD(ans[k].sum[i],1ll*x*ans[k].sum[j]%mod*C[siz[k]-j][i-j]%mod); 76 MOD(ans[k].sum[i],1ll*x*C[siz[k]][i]%mod); 77 } 78 } 79 80 void turn(int k) 81 { 82 rev[k]^=1; 83 if(f[k]) f[k]=mod-f[k]; 84 for(int i=9;i>0;i-=2) 85 if(ans[k].sum[i]) ans[k].sum[i]=mod-ans[k].sum[i]; 86 } 87 88 void down(int k) 89 { 90 if(rev[k]) turn(k<<1),turn(k<<1|1),rev[k]=0; 91 if(f[k]) insert(k<<1,f[k]),insert(k<<1|1,f[k]),f[k]=0; 92 } 93 94 void add(int k,int l,int r,int opl,int opr,int w) 95 { 96 if(l>=opl && r<=opr) { insert(k,w); return; } 97 down(k); 98 if(opl<=mid[k]) add(k<<1,l,mid[k],opl,opr,w); 99 if(opr>mid[k]) add(k<<1|1,mid[k]+1,r,opl,opr,w); 100 update(k); 101 } 102 103 void reverse(int k,int l,int r,int opl,int opr) 104 { 105 if(l>=opl && r<=opr) { turn(k); return; } 106 down(k); 107 if(opl<=mid[k]) reverse(k<<1,l,mid[k],opl,opr); 108 if(opr>mid[k]) reverse(k<<1|1,mid[k]+1,r,opl,opr); 109 update(k); 110 } 111 112 node query(int k,int l,int r,int opl,int opr,int w) 113 { 114 if(l>=opl && r<=opr) return ans[k]; 115 down(k); 116 if(opr<=mid[k]) return query(k<<1,l,mid[k],opl,opr,w); 117 else if(opl>mid[k]) return query(k<<1|1,mid[k]+1,r,opl,opr,w); 118 else 119 { 120 node L=query(k<<1,l,mid[k],opl,opr,w),R=query(k<<1|1,mid[k]+1,r,opl,opr,w); 121 node tmp; 122 for(int i=1;i<=w;i++) 123 { 124 tmp.sum[i]=(L.sum[i]+R.sum[i])%mod; 125 for(int j=1;j<i;j++) MOD(tmp.sum[i],1ll*L.sum[j]*R.sum[i-j]%mod); 126 } 127 return tmp; 128 } 129 } 130 131 int main() 132 { 133 freopen("game.in","r",stdin); 134 freopen("game.out","w",stdout); 135 int n,m; 136 read(n); read(m); 137 pre(n); 138 build(1,1,n); 139 int ty,l,r,w; 140 while(m--) 141 { 142 read(ty); read(l); read(r); 143 if(ty==1) 144 { 145 read(w); w%=mod; 146 w+= w<0 ? mod : 0; 147 add(1,1,n,l,r,w); 148 } 149 else if(ty==2) reverse(1,1,n,l,r); 150 else 151 { 152 read(w); 153 node p=query(1,1,n,l,r,w); 154 printf("%d\n",query(1,1,n,l,r,w).sum[w]); 155 } 156 } 157 }
View Code
T3https://www.luogu.org/problem/show?pid=T14737
没看懂题目。。。。
总结
、。、、今天的考试确实没有昨天那么水了,,,,
不过,,我好菜啊。。。。。。
转载于:https://www.cnblogs.com/zwfymqz/p/7725995.html
学大伟业Day解题报告相关推荐
- 学大伟业Day1解题报告
学大伟业Day1解题报告 张炳琪 一. 时间分配 T1:30分钟 T2: 60分钟 T3:100分钟 二.答题情况及错因 T1:100 T2:55 T3 ...
- 学大伟业:如何利用课余时间学习物理竞赛,搞定自主招生?
今天撇开能力超强的学生不谈,仅针对目标自主招生的学生,谨慎的给出一些物理竞赛的学习建议. 高一 高中物理竞赛中力学.电磁学模块占据了70%的考试内容,这两个模块也是最难的模块,热学.光学.近代物理内容 ...
- 学大伟业:学长是如何对待数学竞赛的
如果你是下定决心要学数竞,真的很认真地做了决定,那么你的自学能力必须要过关,专注度一定要够强.当然,这里的专注度不是指40分钟过去了,才连一条几何辅助线,也不是说60分钟过去了,你才完成了一试的填空题 ...
- 学大伟业:在数学竞赛学习中,你属于哪种类型?
学习数学竞赛,在其他人眼中是一种什么存在,你知道么? 你在学习数学竞赛中属于什么类型的,你自己知道么? 下面几种类型, 赶紧看看自己,中枪了没. 做题狂魔型 这类人的主要特征就是喜欢做题,简直到了一种 ...
- 学大伟业2018-2019学年第二学期《自主招生集训课程》
尊敬的校长.主任.老师: 您好! 北京学大伟业教育科技有限公司是专注学科奥林匹克竞赛.高校自主招生.高考培优.美加游学.艺术培训的高端品牌教育机构.我们秉承"共育人才,开创未来"的 ...
- 学大伟业:2019年数学竞赛学习经验分享
学习是一个持之以恒的过程,需要不断探索.不断前行.在这路上,我认为最重要的是学习心态.每个人都不可避免地会遇到自己的学习困难,产生消极的想法.有区分度的是能否及时调整好自己,再重新投入到学习中去.身处 ...
- 学大伟业(杭州分校)数学联赛 GA3-1 国奥专题班
北京学大伟业(bjxdwy)杭州分校2019课程于4月4日至4月7日开课,名师生齐聚课堂,助力2019五项学科竞赛!冲刺c9名校!
- 学大伟业:高二才开始学化学竞赛还来得及吗?
很多人都在烦恼,到底什么时候学竞赛最合适?对于化学竞赛来说,初三是最适合入门的阶段,但很多同学和家长因为信息了解不及时,导致到了高一下学期,甚至高二开学才知道竞赛这件事,非常吃亏. 说句实话,如果从高 ...
- 学大伟业:2019年生物竞赛学习方法
1.植物形态解剖学 个人认为是好学的一门科目.植物解剖学历史久远,因此具有一种醇厚的生物学味道,知识不少但是成体系,条理清楚,结论明确,而且不乏可比较记忆者.例如营养器官的结构,就可以从几个维度进行比 ...
最新文章
- 导师:学CV的不懂目标检测?那你别学了
- 2012年欧洲杯德国战车止步四强赛
- Linux内核链表 内存屏障,为什么需要内存屏障
- 命令行分析java线程CPU占用
- java 抽象工厂模式简单实例
- python 加密解密_Python中的加密和解密
- 145_Power BI Report Server自定义Form登录
- Linux学习笔记(四)之查看登录用户
- php判断平年和闰年,平年和闰年的三种判断方法
- 安装JDK失败,再次安装时出现已经安装过了的,解决办法
- Hive:添加、删除分区
- 什么情况下document.write会覆盖页面及覆盖原理解释
- 应用时间序列分析(王燕)学习笔记1
- Echarts制作动态K线图和分时图
- 《汽车之家》字体反爬之论坛、问答、文章(新闻、车家号)及其评论爬取
- JFrame中添加背景音乐
- Git分支 合并 暂时储藏分支 标签 链接多个仓库
- 声音大小与振幅的关系_物理知识问答-响度与振幅的关系是什么?
- NO.2 微信第三方平台(小程序)授权流程技术说明
- 【亲测可用】2022最新酒桌小游戏喝酒小程序源码_带流量主