[关闭]
@suixinhita 2017-10-25T08:38:24.000000Z 字数 3860 阅读 727

考前练习-2

t1写挂,t2过了,t3挂了...代码细节是绝对需要注意的啊qwq


T1

此处输入图片的描述

首先,我们定义dp状态:


其中 代表当前位置状态, 为位置。

那么由上面可得方程如下:

注意第一个的初始化不能为 ,最后一个的状态不能为

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define ll long long
  6. using namespace std;
  7. const int N=1e6+5;
  8. const int Q=1e9+7;
  9. char s[N];
  10. ll cnt[5][N],ans;//0 -->0 1-->front(1) 2--> 2 3-->back(1) 4-->mine
  11. int n;
  12. void solve()
  13. {
  14. if(s[1]=='?') cnt[0][2]=cnt[3][3]=cnt[4][4]=1;
  15. else if(s[1]=='0') cnt[0][5]=1;
  16. else if(s[1]=='1') cnt[3][6]=1;
  17. else if(s[1]=='*') cnt[4][7]=1;
  18. for(int i=2;i<=n;++i)
  19. {
  20. if(s[i]=='?')
  21. {
  22. cnt[0][i]=(cnt[0][i-1]+cnt[1][i-1])%Q;
  23. if(i!=n) cnt[3][i]=(cnt[0][i-1]+cnt[1][i-1])%Q;
  24. cnt[1][i]=cnt[4][i-1];
  25. if(i!=n) cnt[2][i]=cnt[4][i-1];
  26. cnt[4][i]=((cnt[3][i-1]+cnt[2][i-1])%Q+cnt[4][i-1])%Q;
  27. }
  28. else
  29. {
  30. if(s[i]=='0') cnt[0][i]=(cnt[0][i-1]+cnt[1][i-1])%Q;
  31. else if(s[i]=='1')
  32. {
  33. cnt[1][i]=cnt[4][i-1];
  34. cnt[3][i]=(cnt[0][i-1]+cnt[1][i-1])%Q;
  35. }
  36. else if(s[i]=='2') cnt[2][i]=cnt[4][i-1];
  37. else if(s[i]=='*') cnt[4][i]=((cnt[3][i-1]+cnt[2][i-1])%Q+cnt[4][i-1])%Q;
  38. }
  39. }
  40. for(int i=0;i<5;++i)
  41. if(i!=3) ans=(ans+cnt[i][n])%Q;
  42. }
  43. int main()
  44. {
  45. // freopen("mine.in","r",stdin);
  46. // freopen("mine.out","w",stdout);
  47. scanf("%s",s+1);
  48. n=strlen(s+1);
  49. solve();
  50. cout<<ans;
  51. return 0;
  52. }

T2

此处输入图片的描述

之前做过的题,然后可以有多种做法,我写的是最短路。

可以很容易证明,对于一个点来说,该点的水的高度取决于四周的水(或者地)的高度(同一个方向水和地取最大)的最小值。
那么很容易直接最短路过去。
注意在更新某个节点的时候,我们更新出来的是当前点的水值和高度值之间的最大值。

  1. #include<queue>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #define ll long long
  7. using namespace std;
  8. const int N=305;
  9. const int M=372100;
  10. const ll inf=0x3f3f3f3f3f;
  11. struct data{
  12. int x,y;
  13. }dot[M];
  14. int m,n;
  15. ll dis[N][N];
  16. int fx[5]={0,0,0,1,-1};
  17. int fy[5]={0,1,-1,0,0};
  18. bool ind[N][N];
  19. int map[N][N];
  20. void bfs(int x)
  21. {
  22. queue<data> q;
  23. data k;k.x=k.y=1;
  24. q.push(k);
  25. while(!q.empty())
  26. {
  27. data k=q.front();q.pop();
  28. dis[k.x][k.y]=max(dis[k.x][k.y],map[k.x][k.y]);
  29. for(int k=1;k<=4;++k)
  30. {
  31. int x=k.x+fx[k],y=k.y+fy[k];
  32. if(x<1||x>n) continue;
  33. if(y<1||y>m) continue;
  34. if(dis[x][y]>dis[k.x][k.y])
  35. {
  36. dis[x][y]=dis[k.x][k.y];
  37. if(!ind[x][y])
  38. {
  39. ind[x][y]=1;
  40. data f;f.x=x,f.y=y;
  41. q.push(f);
  42. }
  43. }
  44. }
  45. ind[k.x][k.y]=0;
  46. }
  47. }
  48. inline int read()
  49. {
  50. int x=0,y=1;char c=getchar();
  51. while(c<'0'||c>'9')
  52. {
  53. if(c=='-') y=-1;
  54. c=getchar();
  55. }
  56. while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
  57. return x*y;
  58. }
  59. void init()
  60. {
  61. for(int i=1;i<=n;++i)
  62. for(int j=1;j<=m;++j)
  63. map[i][j]=read();
  64. for(int i=1;i<=n;++i)
  65. dis[i][1]=max(map[i][1],0),dis[i][m]=max(map[i][m],0);
  66. for(int j=1;j<=m;++j)
  67. dis[1][j]=max(map[i][j],0),dis[1][j]=max(map[n][j],0);
  68. for(int i=2;i<n;++i)
  69. for(int j=2;j<m;++j) dis[i][j]=inf;
  70. }
  71. int main()
  72. {
  73. freopen("water.in","r",stdin);
  74. freopen("water.out","w",stdout);
  75. n=read(),m=read();
  76. init();
  77. spfa();
  78. for(int i=1;i<=n;++i)
  79. {
  80. for(int j=1;j<=m;++j)
  81. {
  82. ll ans=(dis[i][j]-(ll)map[i][j]);
  83. printf("%lld ",ans<0? 0:ans);
  84. }
  85. puts("");
  86. }
  87. return 0;
  88. }

T3

..

...暴力没过一个点...心累。

首先,我们知道,这题对于 肯定要分解质因数。
然后我们再想,怎么统计集合里面和这个数互质的数???
互质的不好算,我们想想看,用补集转化一下,不就是和 有相同质因子的个数嘛?
这个好像还可做一些...
所以我们可以统计每个值的倍数个数,然后容斥原理计算答案...

  1. #include<queue>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int N=2e6+5;
  6. const int M=5e5+5;
  7. int cnt[500005];
  8. long long ans;
  9. int piece[M][40],sum[M];
  10. int a[N],m,n,x;
  11. bool in[N];
  12. bool vis[M];
  13. void pre_tab()
  14. {
  15. for(int i=2;i<M;++i)
  16. {
  17. if(vis[i]) continue;
  18. for(int j=1;i*j<M;++j)
  19. {
  20. int f=i*j;
  21. vis[f]=1;
  22. piece[f][++sum[f]]=i;
  23. }
  24. }
  25. }
  26. void dfs(int now,int num,int nowit,int ty)
  27. {
  28. if(now>sum[x])
  29. {
  30. if(ty==-1)
  31. cnt[num]--;
  32. ans+=nowit*cnt[num];
  33. if(ty==1)
  34. cnt[num]++;
  35. return ;
  36. }
  37. dfs(now+1,num,nowit,ty);
  38. dfs(now+1,num*piece[x][now],-nowit,ty);
  39. }
  40. inline int read()
  41. {
  42. int x=0;char c=getchar();
  43. while(c<'0'||c>'9') c=getchar();
  44. while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
  45. return x;
  46. }
  47. int main()
  48. {
  49. // freopen("gcd.in","r",stdin);
  50. // freopen("gcd.out","w",stdout);
  51. pre_tab();
  52. n=read(),m=read();
  53. for(int i=1;i<=n;++i) a[i]=read();//broken(i);
  54. for(int i=1;i<=m;++i)
  55. {
  56. x=read();
  57. if(!in[x])
  58. {
  59. in[x]=1;x=a[x];
  60. dfs(1,1,1,1);
  61. }
  62. else
  63. {
  64. in[x]=0;x=a[x];
  65. dfs(1,1,-1,-1);
  66. }
  67. printf("%lld\n",ans);
  68. }
  69. return 0;
  70. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注