期望得分:30+100+0=130

实际得分:30+100+20=150

忍者钩爪

(ninja.pas/c/cpp)

【问题描述】

小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个练习使用钩爪的好地方,决定在这里大显身手。

场景的天花板可以被描述为一个无穷长的数轴,初始小Q挂在原点上。数轴上有N个坐标为整数的圆环供小Q实现钩爪移动。具体操作为:小Q可以将钩爪挂到圆环上,进而荡到关于圆环坐标轴对称的位置。例如小Q在3,圆环在7,则小Q可以通过该圆环移动到11。

现在一个问题难倒了小Q,如何判断自己能否到达某个整点呢?

【输入格式】

第一行两个整数N,M,表示圆环的数量和询问组数

接下来一行共N个整数描述每个圆环的坐标(可重复)

接下来M行每行包含一个整数描述询问

输出格式

共M行对应M个询问,若小Q能移动到目标点,输出Yes,否则输出No

题解(不是我的,所以有问题不要问我):

对于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=; int f=; char c=getchar();
  19. while(!isdigit(c)) { if(c=='-') f=-; c=getchar(); }
  20. while(isdigit(c)) { x=x*+c-''; 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=;i<=n;i++) read(a[i]);
  33. LL gcd=;
  34. for(int i=;i<=n;i++) gcd=getgcd(abs(a[i]-a[]<<),gcd);
  35. LL x;
  36. if(gcd)
  37. {
  38. S.insert();
  39. for(int i=;i<=n;i++) S.insert((*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[]* ? "Yes" : "No");
  52. }
  53. }
  54. }

30暴力

  1. #include<cstdio>
  2. #include<algorithm>
  3.  
  4. using namespace std;
  5.  
  6. int tmp[];
  7.  
  8. int n,a[];
  9.  
  10. bool ok[];
  11.  
  12. void judge()
  13. {
  14. int cnt1=,cnt2=;
  15. for(int i=;i<=n;i++)
  16. if(tmp[i]==) cnt1++;
  17. else if(tmp[i]==-) cnt2++;
  18. if(cnt1==cnt2 || cnt1==cnt2+)
  19. {
  20. int t=;
  21. for(int i=;i<=n;i++) t+=tmp[i]*a[i];
  22. ok[t]=true;
  23. }
  24. }
  25.  
  26. void dfs(int now)
  27. {
  28. if(now==n+)
  29. {
  30. judge();
  31. return;
  32. }
  33. tmp[now]=; dfs(now+);
  34. tmp[now]=; dfs(now+);
  35. tmp[now]=-; dfs(now+);
  36. }
  37.  
  38. int main()
  39. {
  40. freopen("ninja.in","r",stdin);
  41. freopen("ninja.out","w",stdout);
  42. int m;
  43. scanf("%d%d",&n,&m);
  44. for(int i=;i<=n;i++) scanf("%d",&a[i]);
  45. int x;
  46. if(n<=)
  47. {
  48. dfs();
  49. for(int i=;i<=m;i++)
  50. {
  51. scanf("%d",&x);
  52. if(x&) puts("No");
  53. else puts(ok[x>>] ? "Yes" : "No");
  54. }
  55. }
  56. else
  57. {
  58. sort(a+,a+n+);
  59. long long maxn=,minn; int mid=n/;
  60. if(mid==n*)
  61. {
  62. for(int i=;i<=mid;i++) maxn+=a[mid+i]-a[i];
  63. }
  64. else
  65. {
  66. for(int i=;i<=mid;i++) maxn+=a[mid+i+]-a[i];
  67. maxn+=a[mid+];
  68. }
  69. minn=-maxn;
  70. for(int i=;i<=m;i++)
  71. {
  72. scanf("%d",&x);
  73. if(x&) puts("Yes");
  74. else if(x>maxn || x<minn) puts("No");
  75. else puts("Yes");
  76. }
  77. }
  78. }

线段树

先下放取反标记,在下方加标记

下放取反标记时,若存在加标记,加标记也取反

关键是如何处理加标记的影响

设当前线段树区间有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+;
  10.  
  11. typedef long long LL;
  12.  
  13. int n;
  14.  
  15. int C[N][];
  16.  
  17. int f[N<<];
  18. int siz[N<<],mid[N<<];
  19. bool rev[N<<];
  20.  
  21. struct node { int sum[]; }ans[N<<];
  22.  
  23. void read(int &x)
  24. {
  25. x=; int ff=; char c=getchar();
  26. while(!isdigit(c)) { if(c=='-') ff=-; c=getchar(); }
  27. while(isdigit(c)) { x=x*+c-''; c=getchar(); }
  28. x*=ff;
  29. }
  30.  
  31. int tot=;
  32.  
  33. void MOD(int &a,int b)
  34. {
  35. a+=b;
  36. a-= a>=mod ? mod : ;
  37. }
  38.  
  39. void pre(int n)
  40. {
  41. C[][]=;
  42. for(int i=;i<=n;i++)
  43. {
  44. C[i][]=;
  45. for(int j=;j<=min(i,);j++) C[i][j]=(C[i-][j]+C[i-][j-])%mod;
  46. }
  47. }
  48.  
  49. void update(int k)
  50. {
  51. for(int i=;i<=;i++)
  52. {
  53. ans[k].sum[i]=;
  54. for(int j=;j<i;j++) MOD(ans[k].sum[i],1ll*ans[k<<].sum[j]*ans[k<<|].sum[i-j]%mod);
  55. MOD(ans[k].sum[i],ans[k<<].sum[i]); MOD(ans[k].sum[i],ans[k<<|].sum[i]);
  56. }
  57. }
  58.  
  59. void build(int k,int l,int r)
  60. {
  61. siz[k]=r-l+;
  62. if(l==r) { read(ans[k].sum[]); MOD(ans[k].sum[],); return; }
  63. mid[k]=l+r>>;
  64. build(k<<,l,mid[k]); build(k<<|,mid[k]+,r);
  65. update(k);
  66. }
  67.  
  68. void insert(int k,int w)
  69. {
  70. MOD(f[k],w);
  71. for(int i=;i;i--)
  72. {
  73. int x=w;
  74. for(int j=i-;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]^=;
  83. if(f[k]) f[k]=mod-f[k];
  84. for(int i=;i>;i-=)
  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<<),turn(k<<|),rev[k]=;
  91. if(f[k]) insert(k<<,f[k]),insert(k<<|,f[k]),f[k]=;
  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<<,l,mid[k],opl,opr,w);
  99. if(opr>mid[k]) add(k<<|,mid[k]+,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<<,l,mid[k],opl,opr);
  108. if(opr>mid[k]) reverse(k<<|,mid[k]+,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<<,l,mid[k],opl,opr,w);
  117. else if(opl>mid[k]) return query(k<<|,mid[k]+,r,opl,opr,w);
  118. else
  119. {
  120. node L=query(k<<,l,mid[k],opl,opr,w),R=query(k<<|,mid[k]+,r,opl,opr,w);
  121. node tmp;
  122. for(int i=;i<=w;i++)
  123. {
  124. tmp.sum[i]=(L.sum[i]+R.sum[i])%mod;
  125. for(int j=;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(,,n);
  139. int ty,l,r,w;
  140. while(m--)
  141. {
  142. read(ty); read(l); read(r);
  143. if(ty==)
  144. {
  145. read(w); w%=mod;
  146. w+= w< ? mod : ;
  147. add(,,n,l,r,w);
  148. }
  149. else if(ty==) reverse(,,n,l,r);
  150. else
  151. {
  152. read(w);
  153. node p=query(,,n,l,r,w);
  154. printf("%d\n",query(,,n,l,r,w).sum[w]);
  155. }
  156. }
  157. }

GG

20分暴力

  1. #include<cstdio>
  2. #include<cmath>
  3.  
  4. using namespace std;
  5.  
  6. int n,N,d;
  7.  
  8. double a[][],b[];
  9.  
  10. int ty[],tmp[],bit[];
  11.  
  12. double ans;
  13.  
  14. void init()
  15. {
  16. scanf("%d%d",&n,&N);
  17. for(int i=;i<=n;i++)
  18. for(int j=;j<=n;j++)
  19. scanf("%lf",&a[i][j]);
  20. scanf("%d",&d);
  21. for(int i=;i<=n;i++) scanf("%d",&ty[i]);
  22. }
  23.  
  24. void add(double may)
  25. {
  26. int t=;
  27. for(int i=;i<=N;i++) t+=tmp[i]*bit[i-];
  28. b[t]+=may;
  29. }
  30.  
  31. void dfs(int tim,int now,double may)
  32. {
  33. if(tim==N+) { add(may); return; }
  34. for(int i=;i<=n;i++)
  35. {
  36. tmp[tim]=ty[i];
  37. dfs(tim+,i,may*a[now][i]);
  38. }
  39. }
  40.  
  41. int main()
  42. {
  43. freopen("walk.in","r",stdin);
  44. freopen("walk.out","w",stdout);
  45. init();
  46. tmp[]=ty[];
  47. bit[]=; for(int i=;i<=N;i++) bit[i]=bit[i-]*;
  48. dfs(,,1.0);
  49. int tot=pow(,N);
  50. for(int i=;i<tot;i++) ans+=b[i]*b[i];
  51. printf("%.9lf",ans);
  52. }

学大伟业 国庆Day2的更多相关文章

  1. 学大伟业Day1解题报告

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

  2. 学大伟业 2017 国庆 Day1

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

  3. 学大伟业DAY2模拟赛

    T1忍者钩爪 题目描述 小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个练习使用钩爪的好地方,决定在这里大显身手. 场景的天花板可以被描述为一个无穷长的数轴,初始小Q挂在原点上.数轴 ...

  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. [BZOJ4825][HNOI2017]单旋spaly

    BZOJ Luogu 题目太长了,就不放了. 题解 首先声明一点,无论是splay还是spaly,插入一个新的元素,都要rotate到根!所以说题目也算是给了一个错误示范吧. 我们发现把最值旋转到根并 ...

  2. 如何巧妙的利用selenium和requests组合来进行操作需要登录的页面

    一.在这里selenium的作用 (1)模拟的登录. (2)获取登录成功之后的cookies 代码 def start_login(self): chrome_options = Options() ...

  3. JavaScript的基本操作(一)

    JavaScript中有大量的方法可供我们使用,详情可参考:http://jquery.cuishifeng.cn/这也同时导致我们不可能去记住每一个的用法,且开发者每天都在新添更多的方法,所以要想掌 ...

  4. kerberos下JAVA代码操作hbase的方式(客户端方式,应用程序方式)

    (一)如果部署JAVA 代码的主机用户获取了kerberos权限情况下 假设主机名是:client su - client 登录主机后 kinit -kt /keytab的路径/client.keyt ...

  5. SIMD---MMX代码优化

    单指令多数据流,即SIMD(Single Instruction, Multiple Data)指一类能够在单个指令周期内同时处理多个数据元素的指令集,利用的是数据级并行来提高运行效率,典型的代表由I ...

  6. VHDL和verilog应该先学哪个?

    网上有太多的VHDL和verilog比较的文章,基本上说的都是VHDL和verilog之间可以实现同一级别的描述,包括仿真级.寄存器传输级.电路级,所以可以认为两者是等同级别的语言.很多时候会了其中一 ...

  7. C++输入输出总结_输入

    1. 输入输出的本质 C++中的输入输出都是通过流来进行的,而具体的输出输入都是通过对流进行操作来完成的,一般为定向一个流(重定向),清空流,向流里边添加新的元素.C++把输入输出看做字节流,输入时从 ...

  8. BZOJ4825 单旋

    分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap. 画一画图就可以解决这道题了,自己试一下. 代码如下: #include<bits/stdc++.h&g ...

  9. Linux epoll源码--

    Linux系统运行源码剖析-epoll代码注释 理解了中断.等待队列.调度,你就能懂Linux的80%. --老子 转发的话,请注明出处哦:http://www.cnblogs.com/stoneha ...

  10. python笔记之序列

    str字符串 表达:单引号,双引号,反斜杠 'let\'s go.' #只使用单引号,外部使用单引号,内部单引号用反斜杠 "let's go. " #单双引号混合使用 长字符串 使 ...