矩阵游戏

考试时思路一度和正解一样,考试到最后还是打了80分思路,结果80分打炸了只得了40分暴力分

题解

算出来第一列的总值,每次通过加每两列之间的差值得出下一列的总值

算第一列我们只需要让当前点*行增倍的数量就行了

  1. for(ll i=1;i<=n;i++){
  2. nowlie=(nowlie+elephant(i,1)*hang[i])%mod;
  3. sum=(sum+hang[i]);
  4. }

算其他列

  1. nowlie=(nowlie+sum)%mod;

可能这一列会加倍只需乘上就行了

  1. ans=(ans+nowlie*lie[i])%mod;

思路简单代码好打,然而考试我还是打炸了

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define A 1010101
  5. const ll mod=1e9+7;
  6. ll n,m,nowlie=0,sum=0,ans=0,k;
  7. ll lie[A],hang[A];
  8. char c[5];
  9. ll elephant(ll i,ll j){
  10. return ((i-1)*m%mod+j)%mod;
  11. }
  12. int main(){
  13. scanf("%lld%lld%lld",&n,&m,&k);
  14. for(ll i=1;i<=1000000;i++){
  15. hang[i]=1;
  16. lie[i]=1;
  17. }
  18. for(ll i=1,a,x;i<=k;i++){
  19. scanf("%s",c+1);
  20. scanf("%lld%lld",&a,&x);
  21. if(c[1]=='S'){
  22. lie[a]=lie[a]*x%mod;
  23. }
  24. if(c[1]=='R'){
  25. hang[a]=hang[a]*x%mod;
  26. }
  27. }
  28. for(ll i=1;i<=n;i++){
  29. nowlie=(nowlie+elephant(i,1)*hang[i])%mod;
  30. sum=(sum+hang[i]);
  31. }
  32. for(ll i=1;i<=m;i++){
  33. ans=(ans+nowlie*lie[i])%mod;
  34. nowlie=(nowlie+sum)%mod;
  35. }
  36. cout<<ans<<endl;
  37. }

跳房子

莫名和考试时思路相似   其实一点也不相似

$85\%$算法

暴力找循环节,剩下数据经过特殊构造你AC不了的,,,,,,,,,

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. char s[10];
  5. #define A 11111111
  6. ll vis[5100][5100],a[5100][5100];
  7. inline int read(){
  8. register int ret=0,f=1;
  9. register char r;
  10. r=getchar();
  11. while(!isdigit(r)){
  12. if(r=='-') f=-1;
  13. r=getchar();
  14. }
  15. while(isdigit(r)){
  16. ret=ret*10+r-'0';
  17. r=getchar();
  18. }
  19. return f*ret;
  20. }
  21. ll p,nowx=1,nowy=1,top=0,n,m;
  22. ll stax[A],stay[A];
  23. void work(ll x){
  24. ll tot=0;
  25. while(x){
  26. ll nx=nowx,ny=nowy,d2=nx+1,d3=nx-1;
  27. (nx+1==n+1)?d2=1:d2=nx+1;
  28. (nx-1==0)?d3=n:d3=nx-1;
  29. if(ny==m) ny=0;
  30. ll z1=a[nx][ny+1],z2=a[d2][ny+1],z3=a[d3][ny+1];
  31. if(z1>z2&&z1>z3) nowx=nx,nowy=ny+1;
  32. else if(z2>z1&&z2>z3) nowx=d2,nowy=ny+1;
  33. else if(z3>z1&&z3>z2) nowx=d3,nowy=ny+1;
  34. x--;
  35. top++;stax[top]=nowx,stay[top]=nowy;
  36. if(!vis[nowx][nowy])
  37. vis[nowx][nowy]=top;
  38. else{
  39. tot=top-vis[nowx][nowy];
  40. x=x%tot;
  41. }
  42. }
  43. while(top){
  44. ll x=stax[top],y=stay[top];
  45. vis[x][y]=0;
  46. top--;
  47. }
  48. printf("%lld %lld\n",nowx,nowy);
  49. }
  50. int main(){
  51. n=read(),m=read();
  52. for(ll i=1;i<=n;i++)
  53. for(ll j=1;j<=m;j++)
  54. a[i][j]=read();
  55. p=read();
  56. for(ll i=1,aa,bb,cc;i<=p;i++){
  57. scanf("%s",s+1);
  58. if(s[1]=='m'){
  59. cc=read();
  60. work(cc);
  61. }
  62. if(s[1]=='c'){
  63. aa=read(),bb=read(),cc=read();
  64. a[aa][bb]=cc;
  65. }
  66. }
  67. }

$100\%$算法

和找循环节类似但又有很大区别,

思考循环节问题出现在那?

可能会遍历整张图才找到一个循环节,即使你预处理了找到循环节,那么出现change正好改掉循环节,再move找循环节,再change 再move你就被卡死了,复杂度本身就有问题

那么没办法做了吗

建立置换,走到一个点,如果步数大就直接置换,步数小就暴力走

我们用一个线段树来维护这个置换如果从1--m建树,那么t[1]就表示走m步置换成哪里

每次走m步

走的次数就是v/m

根据置换的运算$t^k$就是走了k次每次走t步

通过快速幂算出置换得出结果

那么我们经过%可以快速算出来剩下的,剩下的步数暴力走即可

顺便学了置换的运算

c.g[i]=a.g[t.g[i]];

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define A 1010101
  5. ll n,m,k,nowx=1,nowy=1;
  6. ll f[2100][2100];
  7. char znsbc[10];
  8. struct node{
  9. ll g[2100];
  10. node(){
  11. for(ll i=1;i<=n;i++)
  12. g[i]=i;
  13. }
  14. node operator *(const node &a){
  15. node t=*this,c;
  16. for(ll i=1;i<=n;i++)
  17. c.g[i]=a.g[t.g[i]];
  18. return c;
  19. }
  20. }nxt[2100];
  21. struct tree{
  22. ll l,r,f;
  23. node t;
  24. }tr[10100];
  25. inline void up(ll p){
  26. tr[p].t=tr[p<<1].t*tr[p<<1|1].t;
  27. return ;
  28. }
  29. inline void built(ll p,ll l,ll r){
  30. tr[p].l=l,tr[p].r=r;
  31. if(l==r){
  32. tr[p].t=nxt[l];
  33. return ;
  34. }
  35. ll mid=(l+r)>>1;
  36. built(p<<1,l,mid);
  37. built(p<<1|1,mid+1,r);
  38. up(p);
  39. }
  40. inline void add(ll p,ll o){
  41. // printf("l=%lld r=%lld\n",l,r);
  42. if(tr[p].l==tr[p].r){
  43. tr[p].t=nxt[o];
  44. return ;
  45. }
  46. ll mid=(tr[p].l+tr[p].r)>>1;
  47. if(mid>=o)
  48. add(p<<1,o);
  49. else
  50. add(p<<1|1,o);
  51. up(p);
  52. }
  53. inline node meng(node x,ll k){
  54. node ans;
  55. for(;k;k>>=1,x=x*x)
  56. if(k&1)
  57. ans=ans*x;
  58. return ans;
  59. }
  60. inline ll get(ll k,ll flag){
  61. if(k==(flag?m+1:n+1))
  62. return 1;
  63. if(!k)
  64. return flag?m:n;
  65. return k;
  66. }
  67. inline void change(ll xx,ll yy){
  68. ll maxn=0;
  69. xx=get(xx,0);
  70. yy=get(yy,1);
  71. for(ll i=-1;i<=1;i++){
  72. ll x=get(xx+i,0),y=get(yy+1,1);
  73. if(maxn<f[x][y]) maxn=f[x][y],nxt[yy].g[xx]=x;
  74. }
  75. return ;
  76. }
  77. inline void move(ll x){
  78. while(x)
  79. x--,nowx=nxt[nowy].g[nowx],nowy=get(nowy+1,1)/*,printf("x=%lld\n",x)*/;
  80. }
  81. int main(){
  82. scanf("%lld%lld",&n,&m);
  83. for(ll i=1;i<=n;i++)
  84. for(ll j=1;j<=m;j++)
  85. scanf("%lld",&f[i][j]);
  86. for(ll i=1;i<=n;i++)
  87. for(ll j=1;j<=m;j++)
  88. change(i,j);
  89. built(1,1,m);
  90. scanf("%lld",&k);
  91. for(ll i=1,a,b,c,v,o;i<=k;i++){
  92. scanf("%s",znsbc+1);
  93. if(znsbc[1]=='m'){
  94. scanf("%lld",&v);
  95. ll len=min(v,m-nowy+1);
  96. move(len);
  97. v-=len;
  98. if(v){
  99. nowx=meng(tr[1].t,v/m).g[nowx];
  100. v%=m;
  101. if(v){
  102. move(v);
  103. }
  104. }
  105. printf("%lld %lld\n",nowx,nowy);
  106. }
  107. else{
  108. scanf("%lld%lld%lld",&a,&b,&c);
  109. f[a][b]=c;
  110. for(ll j=-1;j<=1;j++)
  111. change(a+j,b-1)/*,printf("*****\n");*/;
  112. o=get(b-1,1);
  113. add(1,o);
  114. }
  115. }
  116. }

随机数据生成

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. ll random(ll n)
  5. {
  6. return rand()%n;
  7. }
  8. bool a[3210520];
  9. int main()
  10. {
  11. freopen("mkd.txt","w",stdout);
  12. srand((unsigned)time(0));
  13. ll n=random(5)+5,m=random(5)+5;
  14. printf("%lld %lld\n",n,m);
  15. for(ll i=1;i<=n;i++,puts(""))
  16. for(ll j=1;j<=m;j++){
  17. ll x=random(550);
  18. while(a[x]) x=random(550);
  19. printf("%lld ",x);
  20. }
  21. ll k=random(50)+50;
  22. printf("%lld\n",k);
  23. for(ll i=1;i<=k;i++)
  24. {
  25. ll op=random(2);
  26. if(op) {
  27. printf("move ");
  28. printf("%lld\n",random(50000)+50000);
  29. }
  30. else{
  31. printf("change ");
  32. ll l=random(n)+1;
  33. ll r=random(m)+1;
  34. printf("%lld %lld %lld\n",l,r,random(50)+50);
  35. }
  36. }
  37. fclose(stdout);
  38. }

t3做法尤其玄学

做法1,把序列问题转化为图论????????线段树优化建边+tarjan缩点+线段树维护图中内容我不会

做法2,扫描线,一条性质,若a<=b<=c<=d并且a--c是好区间,b--d是好区间,那么a--d是好区间

假设我们扫描到i i+1,那么如果i i+1在好区间里,那么val[i] val[i+1]都在好区间里,

设好的二元组为相邻两个数,那么区间若为好区间好二元组数量为r-l

用一棵线段树维护二元组数量设为v,若v+l=r则是好区间,假设我们当前扫描到了a[i],那么处于a[i]-1  a[i]+1的位置都要加1

线段树维护一下,细节比较多

做法3,性质若r-l=maxval-minval那么就是一个好区间

那么若maxval到minval之间全部出现那么是一个好区间,那么位置最左最右值出现即可,,

线段树维护一下||st表维护一下

但做法3本身复杂度不对,随机数据下表现优秀,但会被特殊数据卡

分块优化一下

  1. #include<bits/stdc++.h>
  2. #define MAXN 100005
  3. #define min(a,b) ((a<b)?(a):(b))
  4. #define max(a,b) ((a>b)?(a):(b))
  5. using namespace std;
  6. int mn[20][MAXN],mx[20][MAXN],mh[MAXN],a[MAXN],n,mnpos[20][MAXN],mxpos[20][MAXN],ans1[2005][2005],ans2[2005][2005],t;
  7. int bl[MAXN];
  8. vector<int>ld;
  9. void pre()
  10. {
  11. for(int i=1;i<=n;i++)
  12. for(int j=17;j>=0;j--)
  13. if(i>=(1<<j))
  14. {
  15. mh[i]=j;
  16. break;
  17. }
  18. for(int i=1;i<=17;++i)
  19. for(int j=1;j<=n;++j)
  20. {
  21. mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
  22. mx[i][j]=max(mx[i-1][j],mx[i-1][j+(1<<(i-1))]);
  23. mnpos[i][j]=min(mnpos[i-1][j],mnpos[i-1][j+(1<<(i-1))]);
  24. mxpos[i][j]=max(mxpos[i-1][j],mxpos[i-1][j+(1<<(i-1))]);
  25. }
  26. return ;
  27. }
  28. /*const int L=1<<20|1;
  29. char buffer[L],*S,*T;
  30. #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)*/
  31. inline int Rd()
  32. {
  33. int x=0;char c=getchar();
  34. while(c>'9'||c<'0')c=getchar();
  35. while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
  36. return x;
  37. }
  38. inline int gmax(int l,int r)
  39. {
  40. return max(mx[mh[r-l+1]][l],mx[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
  41. }
  42. inline int gmin(int l,int r)
  43. {
  44. return min(mn[mh[r-l+1]][l],mn[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
  45. }
  46. inline int qmax(int l,int r)
  47. {
  48. return max(mxpos[mh[r-l+1]][l],mxpos[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
  49. }
  50. inline int qmin(int l,int r)
  51. {
  52. return min(mnpos[mh[r-l+1]][l],mnpos[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
  53. }
  54. int main()
  55. {
  56. // freopen("sequence21.in","r",stdin);
  57. n=Rd();
  58. t=pow(n,0.7);
  59. for(int i=1;i<=n;i++)
  60. {
  61. a[i]=Rd();
  62. mn[0][i]=mx[0][i]=a[i];
  63. mnpos[0][a[i]]=mxpos[0][a[i]]=i;
  64. }
  65. int p=0,tot=0;
  66. while(p<n)
  67. {
  68. ld.push_back(p+1);
  69. for(int i=1;i<=t;i++)bl[p+i]=tot;
  70. p+=t;
  71. tot++;
  72. }
  73. pre();
  74. memset(ans1,0x3f,sizeof(ans1));
  75. memset(ans2,-0x3f,sizeof(ans2));
  76. for(int i=0;i<ld.size();i++)
  77. for(int j=i;j<ld.size();j++)
  78. {
  79. int l,r;
  80. l=ld[i];
  81. r=ld[j];
  82. int nowmin=gmin(l,r),nowmax=gmax(l,r);
  83. int pl=qmin(nowmin,nowmax),pr=qmax(nowmin,nowmax);
  84. while(l>pl||r<pr)
  85. {
  86. if(l>pl)
  87. {
  88. nowmin=min(nowmin,gmin(pl,l));
  89. nowmax=max(nowmax,gmax(pl,l));
  90. l=pl;
  91. }
  92. if(r<pr)
  93. {
  94. nowmin=min(nowmin,gmin(r,pr));
  95. nowmax=max(nowmax,gmax(r,pr));
  96. r=pr;
  97. }
  98. pl=qmin(nowmin,nowmax);pr=qmax(nowmin,nowmax);
  99. }
  100. ans1[i][j]=l;ans2[i][j]=r;
  101. // cout<<ans1[i][j]<<' '<<ans2[i][j]<<endl;
  102. }
  103. int Q;
  104. Q=Rd();
  105. while(Q--)
  106. {
  107. register int l,r,ll,rr;
  108. l=Rd();r=Rd();
  109. ll=bl[l]+1;rr=bl[r]-1;
  110. int nowmin=gmin(l,r),nowmax=gmax(l,r);
  111. int pl=qmin(nowmin,nowmax),pr=qmax(nowmin,nowmax);
  112. while(l>pl||r<pr)
  113. {
  114. ll=bl[l]+1;rr=bl[r]-1;
  115. if(l>pl)
  116. {
  117. nowmin=min(nowmin,gmin(pl,l));
  118. nowmax=max(nowmax,gmax(pl,l));
  119. l=pl;
  120. l=min(l,ans1[ll][rr]);
  121. }
  122. if(r<pr)
  123. {
  124. nowmin=min(nowmin,gmin(r,pr));
  125. nowmax=max(nowmax,gmax(r,pr));
  126. r=pr;
  127. r=max(r,ans2[ll][rr]);
  128. }
  129. pl=qmin(nowmin,nowmax);pr=qmax(nowmin,nowmax);
  130. }
  131. printf("%d %d\n",l,r);
  132. }
  133. return 0;
  134. }

NOIP模拟测试13「矩阵游戏&#183;跳房子&#183;优美序列」的更多相关文章

  1. NOIP模拟测试24「star way to hevaen·lost my music」

    star way to heaven 题解 大致尝试了一下并查集,记忆化搜索,最小生成树 最小生成树是正解,跑最小生成树然后找到最大的值 欧几里德距离最小生成树学习 prim楞跑 至于为什么跑最小生成 ...

  2. 8.5 NOIP模拟测试13 矩阵游戏+跳房子+优美序列

    T1矩阵游戏 数学题.首先这一列这一行先乘还是后乘对最后答案没有影响.a[i][j]表示矩阵中原始的值,h[i]表示i行的累乘,l[i]表示i列的累乘.易得ans=Σa[i][j]*h[i]*l[i] ...

  3. NOIP模拟测试13

    考得还算可以,T3还有提升空间(没看清题&&样例没过 拿了4分). 期望得分:80+40+0=120 实际得分:80+85+4=169 一脸黑线.....是数据比较水的原因,T2分都比 ...

  4. 2019.8.5 NOIP模拟测试13 反思总结【已更新完毕】

    还没改完题,先留个坑. 放一下AC了的代码,其他东西之后说… 改完了 快下课了先扔代码 跑了跑了 思路慢慢写 来补完了[x 刚刚才发现自己打错了标题 这次考试挺爆炸的XD除了T3老老实实打暴力拿了52 ...

  5. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

  6. 8.5 NOIP 模拟测试 13

    今天的考试说实话T1很简单没A,我是傻X.T2T3难得一批,但是暴力的分还是拿了! 总结一下就是:骗分过样例,暴力出奇迹!只要瞎搞就行了! 话说现在终于不像之前那么傻了,终于知道打暴力了,因为之前暴力 ...

  7. NOIP模拟测试21「折纸&#183;不等式」

    折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...

  8. NOIP模拟测试17「入阵曲&#183;将军令&#183;星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

  9. NOIP模拟测试11「string&#183;matrix&#183;big」

    打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...

随机推荐

  1. 【Tavern】1.tavern测试框架介绍

    目录 1. Tavern 和 Postman 2. 安装Python 3. 安装Tavern 4. 第一个测试用例 1. Tavern 和 Postman Tavern是一个用Python实现的接口自 ...

  2. SQL必知必会 —— 性能优化篇

    数据库调优概述 数据库中的存储结构是怎样的 在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载.也就是说,数据库管理存储空间的基本单位是页(Page). 一个页中可以存储多个行记录(Ro ...

  3. C#中的元组(Tuple)和结构体(struct)

    在正常的函数调用中,一个函数只能返回一个类型的值,但在某些特殊情况下,我们可能需要一个方法返回多个类型的值,除了通过ref,out或者泛型集合可以实现这种需求外,今天,讲一下元组和结构体在这一方面的应 ...

  4. C++入门教程之二:变量

    C++入门教程之二:变量 变量,顾名思义,意思是变化的量.变量的定义是计算机语言中能储存计算结果或能表示值的抽象概念.一个基本的程序需要变量,因此变量是程序设计中的一大重点. 变量基本结构 var_t ...

  5. 【Azure Developer】使用Microsoft Graph API 如何批量创建用户,用户属性中需要包含自定义字段(如:Store_code,Store_name等)

    Microsoft Graph 是 Microsoft 365 中通往数据和智能的网关. 它提供统一的可编程模型,可用于访问 Microsoft 365.Windows 10 和企业移动性 + 安全性 ...

  6. IntelliJ IDEA 老司机,还没用过 Stream Trace 功能?

    前言 自从 Java 8 开始,作为程序员的我们都离不开 Stream 相关功能的使用,书写起来那叫一个流畅(这个 feel--).但总是有一些时候,我们对 stream 的操作所要的结果和预期不符, ...

  7. Pytorch_Part6_正则化

    VisualPytorch beta发布了! 功能概述:通过可视化拖拽网络层方式搭建模型,可选择不同数据集.损失函数.优化器生成可运行pytorch代码 扩展功能:1. 模型搭建支持模块的嵌套:2. ...

  8. wmctrl像xmonad那样方便地用快捷键来控制任务窗口的显示

    窗口左右互搏之wmctrl篇 分类: LINUX 2012-10-24 16:34:41   一直有个念头,就是能够像xmonad那样方便地用快捷键来控制任务窗口的显示,今天弄wmctrl,刚好有时间 ...

  9. 分布式存储ceph---部署ceph(2)

    一.部署准备 准备5台机器(linux系统为centos7.6版本),当然也可以至少3台机器并充当部署节点和客户端,可以与ceph节点共用: 1台部署节点(配一块硬盘,运行ceph-depoly) 3 ...

  10. C语言函数sscanf()的用法-(转自Walter L)

    在我的学习过程中,从文件读取数据是一件很麻烦的事,所幸有sscanf()函数. C语言函数sscanf()的用法sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: int ss ...