\(\\\)

\(Day\ 1\)


\(\\\)

\(\#\ A\) \(Rps\)


定义五种方案的石头剪刀布游戏,两人共进行\(N\)局游戏,已知两人各自的循环节和具体方案,胜者得\(1\)分,败者或平局均不得分,求\(N\)局后两人得分。

  • \(N\in [0,200]\)
  • 将二维的计分表填满,模拟。
  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define N 210
  9. #define n1 x[0]
  10. #define n2 y[0]
  11. #define R register
  12. #define gc getchar
  13. using namespace std;
  14. int n,x[N],y[N];
  15. int res[5][5]={
  16. {0,0,1,1,0},
  17. {1,0,0,1,0},
  18. {0,1,0,0,1},
  19. {0,0,1,0,1},
  20. {1,1,0,0,0}
  21. };
  22. inline int rd(){
  23. int x=0; bool f=0; char c=gc();
  24. while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  25. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  26. return f?-x:x;
  27. }
  28. int main(){
  29. n=rd(); n1=rd(); n2=rd();
  30. for(R int i=1;i<=n1;++i) x[i]=rd();
  31. for(R int i=1;i<=n2;++i) y[i]=rd();
  32. int px=0,py=0,ansx=0,ansy=0;
  33. for(R int i=1;i<=n;++i){
  34. px=(px==n1)?1:px+1;
  35. py=(py==n2)?1:py+1;
  36. ansx+=res[x[px]][y[py]];
  37. ansy+=res[y[py]][x[px]];
  38. }
  39. printf("%d %d",ansx,ansy);
  40. return 0;
  41. }

\(\\\)

\(\# B\) \(Link\)


给出一棵\(N\)个节点的树,每个边的边权都为\(1\),每个点都有权值\(W_i\),对于图\(G\)上的任意点对\((u,v)\),若它们的最短距离为\(2\),则它们之间会产生\(W_v \times W_u\)的联合权值,求:

  • 整棵树所有点对中能够产生的最大联合权值
  • 整棵树的所有能产生联合权值的点对间联合权值之和\((\)对\(10007\)取模\()\)
  • \(N\in [0,2\times 10^5]\),\(W_i\in [0,10^4]\)
  • 每个能产生联合权值的点对必然会跨过一个中间点,也就是说,一个能产生联合权值的点对,必然存在一个另外的点,与这个点对中的两个点有边相连。
  • 考虑枚举这个中间点,那么他直接连边的所有点任选两个都会产生联合权值,考虑用一种类似前缀和的方法,顺序扫描所有出边,每个点只与在它前面被扫描到的点\((\)仅本次枚举中间点所扫描到的点\()\)产生联合权值,这样计数可以保证复杂度对于每个点是线性的,并且不会重复计数。
  • 对于最大值部分只需要在扫描过程中记录当前点所引出的点中最大权值点和次大权值点,每扫描一条出边就尝试更新最大值和次大值,最后得到的两个数相乘就是以当前点为中间点所能产生的最大联合权值。
  • 注意点对是有序的,所以求和部分最后要取双倍答案。
  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define N 200010
  9. #define R register
  10. #define gc getchar
  11. #define mod 10007
  12. using namespace std;
  13. int n,tot,ansmx,ans,hd[N],val[N];
  14. struct edge{int to,nxt;}e[N<<1];
  15. inline void add(int u,int v){
  16. e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
  17. }
  18. inline int rd(){
  19. int x=0; bool f=0; char c=gc();
  20. while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  21. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  22. return f?-x:x;
  23. }
  24. inline void calc(int u){
  25. int sum=0,mx=0,sx=0;
  26. for(R int i=hd[u],v;i;i=e[i].nxt){
  27. v=e[i].to;
  28. if(val[v]>mx){sx=mx;mx=val[v];}
  29. else if(val[v]>sx) sx=val[v];
  30. (ans+=sum*val[v])%=mod;
  31. (sum+=val[v])%=mod;
  32. }
  33. ansmx=max(ansmx,mx*sx);
  34. }
  35. int main(){
  36. n=rd();
  37. for(R int i=1,u,v;i<n;++i){
  38. u=rd(); v=rd(); add(u,v); add(v,u);
  39. }
  40. for(R int i=1;i<=n;++i) val[i]=rd();
  41. for(R int i=1;i<=n;++i) calc(i);
  42. printf("%d %d",ansmx,(ans<<1)%mod);
  43. return 0;
  44. }

\(\\\)

\(\#C\) \(Bird\)


\(Flappy\ Bird\),问题简化到了二维平面上,规定每次向上一次上升高度和每个位置不上升时的下降高度,具体问题描述见题目链接。

  • \(N\in [1,10^4]\),\(M\in [1,10^3]\)
  • 设\(f[i][j]\)表示处理到第\(i\)列,到达高度为\(j\)的最少点击次数。

  • 有显然的初始化\(f[i][j]=\infty\ \bigg|\ i\in[1,N],j\in[0,M]\),注意到起点不能是地面,所以还有\(f[0][0]=\infty\)。

  • 先不考虑水管高度和下降操作,对于每一个坐标\((i,j)\),有显然的\(\text O(NM^2)\)的转移\(\begin{align} f[i][j]=min\{f[i-1][j-k\times up_i]+k\ \big| \ 1≤k≤\frac{j}{up_i}\}\end{align}\)

  • 注意到转移方程都是统一的形式,\(f[i][j-up_i]\)已经帮助完成了除去\(f[i-1][j-up_i]\)以外的其他部分答案的统计,所以转移可以优化成\(\text O(NM)\)的形式:\(\begin{align}f[i][j]=min(f[i-1][j-up_i],f[i][j-up_i])+1\end{align}\)

  • 注意到顶部的限制,\(f[i][M]\)的转移就多了很多,但是同样可以采用类似的方法优化:\(\begin{align}f[i][M]=min\{f[i][k]+1\ \big|\ k\in [M-up_i,M]\}\end{align}\)

  • 然后再考虑下降部分,之所以这样按排顺序,是因为如果先更新下降部分的策略,可能会导致同一位置下降和上升同时出现,不合法。此部分的转移显然:\(\begin{align} f[i][j]=min(f[i][j],f[i-1][j+dn_i]\ \big|\ j+dn_i\le M) \end{align}\)

  • 最后要考虑继续向后更新的合法性,将水管部分的答案全部重置为\(\infty\)。

  • 答案可以倒着寻找,找到一个位置\(DP\)值不为\(\infty\)的即可作为答案,注意同时要更新经过的水管数。

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define N 10010
  9. #define M 1010
  10. #define R register
  11. #define gc getchar
  12. #define inf 2000000000
  13. using namespace std;
  14. int n,m,x,u[N],d[N],mx[N],mn[N],f[N][M];
  15. inline int rd(){
  16. int x=0; char c=gc();
  17. while(!isdigit(c)) c=gc();
  18. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  19. return x;
  20. }
  21. int main(){
  22. n=rd(); m=rd(); x=rd();
  23. for(R int i=1;i<=n;++i){
  24. u[i]=rd(); d[i]=rd(); mx[i]=m; mn[i]=1;
  25. }
  26. for(R int i=1,p;i<=x;++i){
  27. p=rd(); mn[p]=rd()+1; mx[p]=rd()-1;
  28. }
  29. for(R int i=1;i<=n;++i)
  30. for(R int j=0;j<=m;++j) f[i][j]=inf;
  31. for(R int i=1;i<=n;++i){
  32. for(R int j=1;j<=m;++j){
  33. if(j>=u[i]) f[i][j]=min(f[i][j],min(f[i-1][j-u[i]],f[i][j-u[i]])+1);
  34. if(j==m) for(R int k=j-u[i];k<=m;++k)
  35. f[i][j]=min(f[i][j],min(f[i-1][k],f[i][k])+1);
  36. }
  37. for(R int j=mn[i];j<=mx[i];++j)
  38. if(j+d[i]<=m) f[i][j]=min(f[i][j],f[i-1][j+d[i]]);
  39. for(R int j=0;j<mn[i];++j) f[i][j]=inf;
  40. for(R int j=mx[i]+1;j<=m;++j) f[i][j]=inf;
  41. }
  42. int ans=inf,cnt=x;
  43. for(R int i=n;i;--i){
  44. for(R int j=mn[i];j<=mx[i];++j) ans=min(ans,f[i][j]);
  45. if(ans<inf) break;
  46. if(mx[i]<m) --cnt;
  47. }
  48. (cnt==x)?printf("1\n%d\n",ans):printf("0\n%d\n",cnt);
  49. return 0;
  50. }

\(\\\)

\(Day\ 2\)


\(\\\)

\(\#\ A\) \(Wireless\)


一个\(130\times 130\)的表格,一些格点有权,现在挑一个格点为中心选一个边长为\(2d\)的正方形,求这个正方形内\((\)含边界\()\)权值和最大值,以及可以产生此最大值的格点个数。

  • \(d\in [1,20]\),\(V_{ij}\in [0,10^6]\)
  • 显然我们可以讲整个表格求二维前缀和,这样即可\(\Theta(1)\)地求出一个子正方形的权值。
  • 把所有格点扫一遍即可,需要注意的是不能直接枚举子正方形顶点,因为会漏掉以边界为中心的一些子正方形,直接按照题目所说枚举中心点即可避免。
  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define N 150
  9. #define R register
  10. #define gc getchar
  11. using namespace std;
  12. int n,d,res,cnt=1,sum[N][N];
  13. inline int rd(){
  14. int x=0; bool f=0; char c=gc();
  15. while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  16. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  17. return f?-x:x;
  18. }
  19. int main(){
  20. d=rd(); n=rd();
  21. memset(sum,0,sizeof(sum));
  22. for(R int i=1,x,y;i<=n;++i){
  23. x=rd()+1; y=rd()+1; sum[x][y]+=rd();
  24. }
  25. for(R int i=1;i<N;++i)
  26. for(R int j=1;j<N;++j)
  27. sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
  28. for(R int i=1;i<=129;++i)
  29. for(R int j=1;j<=129;++j){
  30. int x=i+d,y=j+d;
  31. int ans=sum[x][y]-sum[max(0,x-2*d-1)][y]-sum[x][max(0,y-2*d-1)]+sum[max(0,x-2*d-1)][max(0,y-2*d-1)];
  32. if(ans==res) ++cnt;
  33. if(ans>res) res=ans,cnt=1;
  34. }
  35. printf("%d %d\n",cnt,res);
  36. return 0;
  37. }

\(\\\)

\(\#B\) \(Road\)


给出一张\(N\)个点\(M\)条边的有向图,且所有边权均为\(1\),现规定起点\(U\)和终点\(V\),找出一条从\(U\)到\(V\)的最短路径,且该路径需满足:路径上的所有点的出边所指向的点都直接或间接与终点连通。

求出符合条件的路径的长度,若不存在一条合法路径则输出"\(-1\)"。

  • \(N\in [2,10^4]\),\(M\in [1,2\times 10^5]\)
  • 把问题转化为最短路,需要去掉所有满足“出边所指向的点中存在不与终点连通的点”的所有点,以及所有不与终点连通的点。

  • 考虑正向求是否可达并不好处理,正难则反,把图建为原图的反图,从\(N\)开始做一遍\(BFS\)即可确定原图中每个点是否与终点连通,这样我们即可去除所有不与终点连通的点。

  • 第一类不合法是由于联通了第二类不合法点导致的,所以在反图中我们同样可以找到原图里联通第二类不合法点的点,把他们也打上不合法标记,注意,这里的标记不能直接在原来存储第二类不合法点的数组中记录

  • 把不合法点都去除后,从\(N\)做一遍最短路即可。

  1. #include<cmath>
  2. #include<queue>
  3. #include<cstdio>
  4. #include<cctype>
  5. #include<cstdlib>
  6. #include<cstring>
  7. #include<iostream>
  8. #include<algorithm>
  9. #define N 10010
  10. #define M 200010
  11. #define R register
  12. #define gc getchar
  13. #define inf 10000000
  14. using namespace std;
  15. bool vis[N],valid[N];
  16. int n,m,tot,hd[N],dis[N],U,V;
  17. struct edge{int to,nxt;}e[M];
  18. inline void add(int u,int v){
  19. e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
  20. }
  21. inline int rd(){
  22. int x=0; bool f=0; char c=gc();
  23. while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  24. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  25. return f?-x:x;
  26. }
  27. queue<int> q;
  28. inline void bfs(){
  29. q.push(V); vis[V]=1;
  30. while(!q.empty()){
  31. int u=q.front(); q.pop();
  32. for(R int i=hd[u],v;i;i=e[i].nxt)
  33. if(!vis[v=e[i].to]){
  34. q.push(v); vis[v]=1;
  35. }
  36. }
  37. for(R int i=1;i<=n;++i) valid[i]=vis[i];
  38. for(R int i=1;i<=n;++i)
  39. if(!vis[i]) for(R int j=hd[i];j;j=e[j].nxt) valid[e[j].to]=0;
  40. }
  41. priority_queue<pair<int ,int> >h;
  42. inline void dij(){
  43. for(R int i=0;i<=n;++i) dis[i]=inf,vis[i]=0;
  44. dis[V]=0; h.push(make_pair(0,V));
  45. while(!h.empty()){
  46. int u=h.top().second; h.pop();
  47. if(vis[u]) continue; vis[u]=1;
  48. for(R int i=hd[u],v;i;i=e[i].nxt)
  49. if(valid[v=e[i].to]&&dis[v]>dis[u]+1){
  50. dis[v]=dis[u]+1; h.push(make_pair(-dis[v],v));
  51. }
  52. }
  53. }
  54. int main(){
  55. n=rd(); m=rd();
  56. for(R int i=1,u,v;i<=m;++i){u=rd(); v=rd(); add(v,u);}
  57. U=rd(); V=rd(); bfs(); dij();
  58. printf("%d\n",dis[U]==inf?-1:dis[U]);
  59. return 0;
  60. }

\(\\\)

\(\#C\) \(Equation\)


已知多项式方程:

\(\begin{align}a_0+a_1x+a_2x^2+\cdots+a_Nx^N=0\end{align}\)

求这个方程在\([1,M]\)内的整数解(\(N\)和\(M\)均为正整数)。

  • \(N\in [1,100]\),\(|a_i|\le 10^{10000}\),\(M\in [0,10^6]\)
  • 秦九韶公式减少方程计算次数,将\(x\)的每一层都嵌套起来,将方程变为如下形式:\(\begin{align}a_0+x(a_1+x(a_2+x(a_3+x(...+xa_n)...)))=0\end{align}\)此时,我们只需计算\(N\)次加法和\(N\)次乘法即可得到等式左边的答案。

  • 枚举\([1,M]\)内的所有数,暴力带入验证即可,注意到系数给的非常大,即使是高精乘法也会超时,我们可以采用哈西的思想,将系数和计算所得都对同一个质数取模,验证最后的答案。这样的做法是不严谨的,所以我们考虑多用几个冲突较少的大质数去完成计算。

  • 下面附的代码在洛谷上可通过,应该是当年\(Noip\)的数据,\(BZOJ\)上的数据加强了,这个版本的代码会超时到死都没有卡过40组数据10s的时限。

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cctype>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define N 110
  9. #define M 1000010
  10. #define R register
  11. #define gc getchar
  12. #define mod1 998244353ll
  13. #define mod2 2147483647ll
  14. #define mod3 3221225473ll
  15. using namespace std;
  16. typedef long long ll;
  17. ll n,m,res[M],a[3][N];
  18. inline void rd(ll p){
  19. bool f=0; char c=gc();
  20. while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  21. while(isdigit(c)){
  22. a[0][p]=((a[0][p]<<1)+(a[0][p]<<3)+(c^48))%mod1;
  23. a[1][p]=((a[1][p]<<1)+(a[1][p]<<3)+(c^48))%mod2;
  24. a[2][p]=((a[2][p]<<1)+(a[2][p]<<3)+(c^48))%mod3;
  25. c=gc();
  26. }
  27. if(f){
  28. a[0][p]=-a[0][p]; a[1][p]=-a[1][p]; a[2][p]=-a[2][p];
  29. }
  30. }
  31. inline bool valid(ll x){
  32. ll ans[3]={0ll,0ll,0ll};
  33. for(R int i=n;i;--i){
  34. ans[0]=(ans[0]+a[0][i])*x%mod1;
  35. ans[1]=(ans[1]+a[1][i])*x%mod2;
  36. ans[2]=(ans[2]+a[2][i])*x%mod3;
  37. }
  38. (ans[0]+=a[0][0])%=mod1;
  39. (ans[1]+=a[1][0])%=mod2;
  40. (ans[2]+=a[2][0])%=mod3;
  41. return (ans[0]==0&&ans[1]==0&&ans[2]==0);
  42. }
  43. int main(){
  44. scanf("%lld%lld",&n,&m);
  45. for(R ll i=0;i<=n;++i) rd(i);
  46. for(R ll i=1;i<=m;++i) if(valid(i)) res[++res[0]]=i;
  47. printf("%lld\n",res[0]);
  48. for(R ll i=1;i<=res[0];++i) printf("%lld\n",res[i]);
  49. return 0;
  50. }

[ NOIP 2014 ] TG的更多相关文章

  1. NOIP 2014 提高组 题解

    NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...

  2. Luogu 1351 NOIP 2014 联合权值(贪心,计数原理)

    Luogu 1351 NOIP 2014 联合权值(贪心,计数原理) Description 无向连通图 G 有 n 个点,n-1 条边.点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi, ...

  3. noip 2014 提高组初赛

    noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...

  4. NOIP 2014 pj & tg

    由于我太弱,去了pj组= = ============================== T1: 傻逼暴力 T2: 傻逼暴力+判断+更新 T3: 手画一下就知道了.算出这个点在第几圈,再使劲yy下在 ...

  5. 洛谷P1328==codevs3716 生活大爆炸版石头剪刀布[NOIP 2014 day1 T1]

    P1328 生活大爆炸版石头剪刀布 1.8K通过 2.6K提交 题目提供者2014白永忻 标签模拟NOIp提高组2014 难度普及- 提交该题 讨论 题解 记录 最新讨论 Who can help m ...

  6. noip 2014 总结

    2014 年的noip 已经结束了,成绩从个人而言不是特别的理想,从今年题的逗的程度,本来是个xxx 就被玩脱了= = 当然现在后悔事没有用的了,不过第二天全屏技术的在最后一小时看到了两道题的错误,然 ...

  7. [NOIP 2014复习]第三章:动态规划——NOIP历届真题回想

    背包型动态规划 1.Wikioi 1047 邮票面值设计 题目描写叙述 Description 给定一个信封,最多仅仅同意粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定全部的邮票数量都 ...

  8. Noip 2014酱油记+简要题解

    好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...

  9. NOIP 2014 提高组 Day1

    期望得分:100+100+50=250 实际得分:100+100+50=250 此次NOIP  ZJ省一分数线:500,SD:345 https://www.luogu.org/problem/lis ...

随机推荐

  1. session 分布式处理-----https://segmentfault.com/a/1190000013447750?utm_source=tag-newest

    第一种:粘性session 粘性Session是指将用户锁定到某一个服务器上,比如上面说的例子,用户第一次请求时,负载均衡器将用户的请求转发到了A服务器上,如果负载均衡器设置了粘性Session的话, ...

  2. [luoguP1922] 女仆咖啡厅桌游吧(奇奇怪怪的树形DP)

    传送门 什么鬼的题? 代码 #include <cstdio> #include <cstring> #include <iostream> #define N 1 ...

  3. [luoguP3252] [JLOI2012]树(DP)

    传送门 树上前缀和. 在树上找一条权值和为 s 的链,其中这个链上的点按深度递增(递减)(不同) dfs 每搜到一个点求它的前缀和 sum[x],放入 set 中. 在 set 中找 sum[x] - ...

  4. A + B Problem Too

    Problem Description This problem is also a A + B problem,but it has a little difference,you should d ...

  5. JavaSE部分之(1)Java基础

    JavaSE部分之(1)Java基础 1.为什么重写equals还要重写hashcode 为了提高程序的效率才实现了hashcode方法,先进行hashcode的比较,如果不同,那就没必要再进行equ ...

  6. 开源的轻量级JSON存储Kinto介绍

    本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2015/12/introducing-kinto Kinto是个提供了同步与分片功能的 ...

  7. android 日历

    [1].[代码] [Java]代码 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  8. Python3基础(九) 错误和异常

    本文主要介绍Python中的错误和异常,涉及到简单的异常处理.抛出异常以及清理动作.至于自定义异常类,将在介绍类与继承的时候讲到. 一.定义 常见的两种错误:语法错误 和 异常. 1.语法错误(Syn ...

  9. Codeforces 196 D. The Next Good String

    D. The Next Good String time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  10. C#邮件发送(含附件)

    class SendEmail { static void Main(string[] args) { string from = "发件人@yingu.com"; string ...