预计分数: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即可,可获得满分。

 #include<set>
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; typedef long long LL; #define N 100001 LL a[N]; set<LL>S; void read(LL &x)
{
x=; int f=; char c=getchar();
while(!isdigit(c)) { if(c=='-') f=-; c=getchar(); }
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
x*=f;
} LL getgcd(LL i,LL j) { return !j ? i : getgcd(j,i%j); } int main()
{
freopen("ninja.in","r",stdin);
freopen("ninja.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) read(a[i]);
LL gcd=;
for(int i=;i<=n;i++) gcd=getgcd(abs(a[i]-a[]<<),gcd);
LL x;
if(gcd)
{
S.insert();
for(int i=;i<=n;i++) S.insert((*a[i]%gcd+gcd)%gcd);
while(m--)
{
read(x);
puts(S.find((x%gcd+gcd)%gcd)!=S.end() ? "Yes" : "No");
}
}
else
{
while(m--)
{
read(x);
puts(x==a[]* ? "Yes" : "No");
}
}
}

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]

 #include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 50001 const int mod=1e9+; typedef long long LL; int n; int C[N][]; int f[N<<];
int siz[N<<],mid[N<<];
bool rev[N<<]; struct node { int sum[]; }ans[N<<]; void read(int &x)
{
x=; int ff=; char c=getchar();
while(!isdigit(c)) { if(c=='-') ff=-; c=getchar(); }
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
x*=ff;
} int tot=; void MOD(int &a,int b)
{
a+=b;
a-= a>=mod ? mod : ;
} void pre(int n)
{
C[][]=;
for(int i=;i<=n;i++)
{
C[i][]=;
for(int j=;j<=min(i,);j++) C[i][j]=(C[i-][j]+C[i-][j-])%mod;
}
} void update(int k)
{
for(int i=;i<=;i++)
{
ans[k].sum[i]=;
for(int j=;j<i;j++) MOD(ans[k].sum[i],1ll*ans[k<<].sum[j]*ans[k<<|].sum[i-j]%mod);
MOD(ans[k].sum[i],ans[k<<].sum[i]); MOD(ans[k].sum[i],ans[k<<|].sum[i]);
}
} void build(int k,int l,int r)
{
siz[k]=r-l+;
if(l==r) { read(ans[k].sum[]); MOD(ans[k].sum[],); return; }
mid[k]=l+r>>;
build(k<<,l,mid[k]); build(k<<|,mid[k]+,r);
update(k);
} void insert(int k,int w)
{
MOD(f[k],w);
for(int i=;i;i--)
{
int x=w;
for(int j=i-;j;j--,x=1ll*x*w%mod)
MOD(ans[k].sum[i],1ll*x*ans[k].sum[j]%mod*C[siz[k]-j][i-j]%mod);
MOD(ans[k].sum[i],1ll*x*C[siz[k]][i]%mod);
}
} void turn(int k)
{
rev[k]^=;
if(f[k]) f[k]=mod-f[k];
for(int i=;i>;i-=)
if(ans[k].sum[i]) ans[k].sum[i]=mod-ans[k].sum[i];
} void down(int k)
{
if(rev[k]) turn(k<<),turn(k<<|),rev[k]=;
if(f[k]) insert(k<<,f[k]),insert(k<<|,f[k]),f[k]=;
} void add(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr) { insert(k,w); return; }
down(k);
if(opl<=mid[k]) add(k<<,l,mid[k],opl,opr,w);
if(opr>mid[k]) add(k<<|,mid[k]+,r,opl,opr,w);
update(k);
} void reverse(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr) { turn(k); return; }
down(k);
if(opl<=mid[k]) reverse(k<<,l,mid[k],opl,opr);
if(opr>mid[k]) reverse(k<<|,mid[k]+,r,opl,opr);
update(k);
} node query(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr) return ans[k];
down(k);
if(opr<=mid[k]) return query(k<<,l,mid[k],opl,opr,w);
else if(opl>mid[k]) return query(k<<|,mid[k]+,r,opl,opr,w);
else
{
node L=query(k<<,l,mid[k],opl,opr,w),R=query(k<<|,mid[k]+,r,opl,opr,w);
node tmp;
for(int i=;i<=w;i++)
{
tmp.sum[i]=(L.sum[i]+R.sum[i])%mod;
for(int j=;j<i;j++) MOD(tmp.sum[i],1ll*L.sum[j]*R.sum[i-j]%mod);
}
return tmp;
}
} int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
int n,m;
read(n); read(m);
pre(n);
build(,,n);
int ty,l,r,w;
while(m--)
{
read(ty); read(l); read(r);
if(ty==)
{
read(w); w%=mod;
w+= w< ? mod : ;
add(,,n,l,r,w);
}
else if(ty==) reverse(,,n,l,r);
else
{
read(w);
node p=query(,,n,l,r,w);
printf("%d\n",query(,,n,l,r,w).sum[w]);
}
}
}

T3https://www.luogu.org/problem/show?pid=T14737

没看懂题目。。。。

总结

、。、、今天的考试确实没有昨天那么水了,,,,

不过,,我好菜啊。。。。。。

学大伟业Day解题报告的更多相关文章

  1. 学大伟业Day1解题报告

    学大伟业Day1解题报告 张炳琪 一.   时间分配 T1:30分钟  T2: 60分钟  T3:100分钟 二.答题情况及错因 T1:100         T2:55             T3 ...

  2. 【九度OJ】题目1190:大整数排序 解题报告

    [九度OJ]题目1190:大整数排序 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1190 题目描述: 对N个长度最长可达 ...

  3. 学大伟业 2017 国庆 Day1

    期望得分:100+100+20=220 实际得分:100+100+20=220 (好久没有期望==实际了 ,~\(≧▽≦)/~) 对于 a........a 如果 第1个a 后面出现的第1个b~z 是 ...

  4. 学大伟业 Day 6 培训总结

    今天接着昨天的继续讲数据结构 今天先是 分块 在统计问题中,尤其是序列问题,经常涉及到区间的操作,比如修改一段区间的元素,询问某个区间的元素的信息. 如果每次都对一整个区间的每一个元素进行操作的话,那 ...

  5. 学大伟业 Day 5 培训总结

    今天讲数据结构 先从mzx大佬的ppt摘抄一段: 数据结构是计算机存储.组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合. 通常情况下,精心选择的数据结构可以带来更高的运行或 ...

  6. 学大伟业 Day 3 培训总结

    今天讲的字符串: 不多说,直接看题 一.表达式求值 题目大意: 输入一行一个表达式,计算其答案 表达式包含非负整数.加减乘除.括号 两种做法 ·栈 ·表达式树 这里更推荐表达式树,因为栈是先压进去,逆 ...

  7. 学大伟业 Day 1 培训总结

    第一天培训,讲的基本算法,东西很多.还有些数论,图论,数据结构and some small tricks 一.输入输出技巧 //输入输出技巧 /* scanf.printf:速度快,需要记忆不同数据类 ...

  8. 学大伟业 Day 2 培训总结

    一.dp 动态规划的本质 是一种思想.通过对原问题划分成子问题,寻找子问题之间的联系,通过求解子问题得出原问题的解.与贪心不同的是,动归是深谋远虑,考虑全局最优解:而贪心则目光短浅,只考虑局部最优解. ...

  9. 2017-10-23学大伟业Day1

    T1 叉叉 题目名称 叉叉 程序文件名 cross 输入文件名 cross.in 输出文件名 cross.out 每个测试点时限 1秒 内存限制 128MB 测试点数目 10 每个测试点分值 10 是 ...

随机推荐

  1. Android控件postDelayed用法,View自带的定时器

    有一个需求是这样的,点击加关注按钮后,执行关注操作,成功后按钮文字变为“已关注”,保持3秒,三秒后按钮文字便问“取消关注”,点击后执行取消关注的操作 源码: public boolean postDe ...

  2. ora_tool

    #!/bin/ksh # # Copyright (c) 1998, 2002, Oracle Corporation.  All rights reserved. #   version() {   ...

  3. Passpoint R1

    Passpoint R1 自从 Android 6.0 支持从网络下载包含配置文件和凭据信息的特殊文件来配置 Passpoint R1(第 1 版)凭据,Android 就一直支持 Passpoint ...

  4. vue中的分页操作

    首先,先看分页的代码: 这里还需要进行操作: 1.分页操作主要传递俩个数据,total和pagenum,一个显示当前页面共有多少条数据,一个是翻页后的操作,看列表的数据能不能跟着改变,在进页面发送请求 ...

  5. PHP取不定个数数组交集

    最近有个需求,有一个N个二维数组,N是动态的,不固定个数,现需取这N个数组的交集内容. 用到的函数是array_intersect_assoc 用法 $result_arr = array_inter ...

  6. struts2.x + Tiles2.x读取多个xml 配置文件

    在web.xml中配置如下即可: <context-param> <param-name>org.apache.tiles.impl.BasicTilesContainer.D ...

  7. hdu-1342 Lotto

    http://acm.hdu.edu.cn/showproblem.php? pid=1342 题意:以升序的形式给定k个数.输出从中挑选6个数满足升序的全部情况. 思路:两个參数.第一个保存当前搜索 ...

  8. 高性能网络编程 - select系统调用

         IO复用使得程序可以同一时候监听多个文件描写叙述符,比方client须要同一时候处理用户输入和网络连接,server端须要同一时候处理监听套接字和连接套接字,select系统调用可以使得我们 ...

  9. JVM调优系列:(四)GC垃圾回收

    跟踪收集算法: 复制(copying): 将堆内分成两个同样空间,从根(ThreadLocal的对象.静态对象)開始訪问每个关联的活跃对象,将空间A的活跃对象所有拷贝到空间B,然后一次性回收整个空间A ...

  10. UITableView去掉最后切割线的一种方法

    UITableView以style:UITableViewStylePlain方式创建时.仅仅要有cell,就会有一条黑线 哪怕至于一个cell也会有,如图 在网上找了集中方法,都不好使,比方http ...