第一题 细胞分裂 大意:
还是细胞分裂的背景,经过x秒后,有很多细胞,每y个细胞会抱团,问剩下的细胞有多少个。对于100%,0≤x<2^233333,y 是3 到1000 之间(含两端)的质数。
解题: 本来觉得挺简单,果然有诈,数据这么大。我还看错了,以为是40%的x<2^64 可以不用高精度,结果是2^x,也就是(2^64)^64,额。然后觉得肯定要用高精度+快速幂。但听说只能过70,所以正解是费马小定理。讲数论的时候没有听懂,现在终于懂了。
费马小定理:x^(b-1)%b=1 设整数p,p/(b-1)为整数,则x^(p/(b-1)*(b-1))%b=x^(b-1)%b=1; 所以:
x^(p/(b-1)*(b-1)+p%(b-1))%b=x^(p%(b-1))%b,即x^p%b=x^(p%(b-1))%b
我们可以把2^x%y的x预处理为较小的数。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<string> 6 #define ll long long 7 using namespace std; 8 int x,y; 9 ll ans=1; 10 char s[100005]; 11 void smaller_x() 12 { 13 char c; 14 int len=strlen(s); 15 for (int i=0;i<len;i++) 16 { 17 c=s[i]; 18 x=((c-'0')+(x<<1)+(x<<3))%(y-1); 19 } 20 } 21 int main(){ 22 freopen("cell.in","r",stdin); 23 freopen("cell.out","w",stdout); 24 scanf("%s%d",s,&y); 25 smaller_x(); 26 for (int i=1;i<=x;i++) 27 ans=(ans*2)%y; 28 cout<<ans; 29 return 0; 30 }
第二题:
通风管
【问题描述】
你只剩6 条管道,他们都是同一型号的弯管。
你必须在指定的空间内装一个管道。空间是一个长方体,所有的边的都是单
位长度的整倍数,可以想象为一个空间堆满了单位正方体。每个弯管占用恰好4
个单位的正方体,如下图1 所示。两个弯管不能重合在同一个单位正方体上。每
个弯管只有2 个口,它们在图形1 中以灰色显示。你可以把2 个弯管接成一根长
的管子,但是它们不得超过给定的空间。图2 表示了其中一种对接方式。你的任
务是接通入口和出口。入口和出口在给定空间的外表面上,和单位正方体对齐,
如图3 所示。为了减少开支,你必须用最少的弯管解决这个问题。
【输入文件】
输入文件为tube.in。
输入包含一行,为11 个用空格隔开的值。
前3 个是整数(xmax,ymax,zmax)表示给定长方体的长宽高。长方体内的每个
单位正方体用坐标(x,y,z)表示, 其中1≤x≤xmax, 1≤y≤ymax, 1≤z≤zmax。
xmax,ymax,zmax 均为正且不大于20。
接下来3 个整数,表示入口所在单位立方体的坐标。
接下来是2 个字符构成的字符串,表示进入的朝向。可能为以下的一种:+
x,-x,+y,-y,+z,-z。举例来说,如果为+y,代表进入的方向为y 轴正方向,所以入
口面向y 轴负方向。
接下来3 个整数,表示出口所在单位立方体的坐标。
最后是2 个字符构成的字符串,表示流出的朝向。可能为以下的一种:+
x,-x,+y,-y,+z,-z。举例来说,如果为+y,代表出去的方向为y 轴正方向,所以出
口面向y 轴正方向。(注意与上面的不同之处。)
【输出文件】
输出文件为tube.out。
输出一行,为接通管道,并且不超过指定空间,最少需要的弯管数。如果不
可能用6 个弯管完成,则输出Impossible。
解:
我几乎用所有的时间在写这道题。。。第一次写长达200+行的代码,就是忘加一个剪枝了,于是T了两个点-_-。不过还是很有成就感,虽然总体上这次考试得的分数不高。我写的dfs,只用了一个增量数组,所以很多判断语句显得很冗长。草稿纸上画了好多图。


1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int zl[4][4]={{0,0,2,-2},{-2,2,0,0},{0,0,1,-1},{-1,1,0,0}}; 7 int x,y,z,st,en,ans=6; 8 int stx,sty,stz,enx,eny,enz; 9 bool can=false,vis[25][25][25]; 10 void init() 11 { 12 cin>>x>>y>>z>>stx>>sty>>stz; 13 char c[5],c2[5]; 14 getchar(); 15 c[0]=getchar(); 16 c[1]=getchar(); 17 cin>>enx>>eny>>enz; 18 getchar(); 19 c2[0]=getchar(); 20 c2[1]=getchar(); 21 if (c[0]=='+'){ 22 if (c[1]=='x') st=1;//left in 23 else if(c[1]=='y') st=3;//front in 24 else if (c[1]=='z') st=5;//down in 25 } 26 else { 27 if (c[1]=='x') st=2;//right in 28 else if(c[1]=='y') st=4;//back in 29 else if (c[1]=='z') st=6;//up in 30 } 31 if (c2[0]=='+'){ 32 if (c2[1]=='x') en=1; 33 else if(c2[1]=='y') en=3; 34 else if (c2[1]=='z') en=5; 35 } 36 else { 37 if (c2[1]=='x') en=2; 38 else if(c2[1]=='y') en=4; 39 else if (c2[1]=='z') en=6; 40 } 41 } 42 int pd12(int j) 43 { 44 if (j==2) return 3; 45 if (j==3) return 4; 46 if (j==0) return 6; 47 if (j==1) return 5; 48 } 49 int pd34(int j) 50 { 51 if (j==2) return 1; 52 if (j==3) return 2; 53 if (j==0) return 6; 54 if (j==1) return 5; 55 } 56 int pd56(int j) 57 { 58 if (j==2) return 1; 59 if (j==3) return 2; 60 if (j==0) return 4; 61 if (j==1) return 3; 62 } 63 void dfs(int dirin,int dirout,int xi,int yi,int zi,int used) 64 { 65 if (used>6) return ; 66 if (dirin==dirout&&xi==enx&&yi==eny&&zi==enz){//到终点且方向相同 67 if (used<=ans) { 68 ans=used; 69 can=true; 70 } 71 return ; 72 } 73 if (used!=0&&dirin==3) yi+=1; 74 if (used!=0&&dirin==4) yi-=1; 75 if (used!=0&&dirin==5) zi+=1; 76 if (used!=0&&dirin==6) zi-=1; 77 if (used!=0&&dirin==1) xi+=1; 78 if (used!=0&&dirin==2) xi-=1; 79 if (dirin==1){ 80 if (xi>=x) return ; 81 for (int i=1;i<=2;i++) 82 for (int j=0;j<=3;j++) 83 { 84 int dir=pd12(j); 85 if (i==1){ 86 int xx=xi+1,yy=yi+zl[0][j],zz=zi+zl[1][j]; 87 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 88 vis[xx][yy][zz]=true; 89 dfs(dir,dirout,xx,yy,zz,used+1); 90 vis[xx][yy][zz]=false; 91 } 92 93 } 94 else{ 95 int xx=xi+2,yy=yi+zl[2][j],zz=zi+zl[3][j]; 96 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 97 vis[xx][yy][zz]=true; 98 dfs(dir,dirout,xx,yy,zz,used+1); 99 vis[xx][yy][zz]=false; 100 } 101 } 102 } 103 } 104 else if (dirin==2){ 105 if (xi<=1) return ; 106 for (int i=1;i<=2;i++) 107 for (int j=0;j<=3;j++) 108 { 109 int dir=pd12(j); 110 if (i==1){ 111 int xx=xi-1,yy=yi+zl[0][j],zz=zi+zl[1][j]; 112 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 113 vis[xx][yy][zz]=true; 114 dfs(dir,dirout,xx,yy,zz,used+1); 115 vis[xx][yy][zz]=false; 116 } 117 } 118 else{ 119 int xx=xi-2,yy=yi+zl[2][j],zz=zi+zl[3][j]; 120 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 121 vis[xx][yy][zz]=true; 122 dfs(dir,dirout,xx,yy,zz,used+1); 123 vis[xx][yy][zz]=false; 124 } 125 } 126 } 127 } 128 else if (dirin==3){ 129 if (yi>=y) return ; 130 for (int i=1;i<=2;i++) 131 for (int j=0;j<=3;j++) 132 { 133 int dir=pd34(j); 134 if (i==1){ 135 int yy=yi+1,xx=xi+zl[0][j],zz=zi+zl[1][j]; 136 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 137 vis[xx][yy][zz]=true; 138 dfs(dir,dirout,xx,yy,zz,used+1); 139 vis[xx][yy][zz]=false; 140 } 141 } 142 else{ 143 int yy=yi+2,xx=xi+zl[2][j],zz=zi+zl[3][j]; 144 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 145 vis[xx][yy][zz]=true; 146 dfs(dir,dirout,xx,yy,zz,used+1); 147 vis[xx][yy][zz]=false; 148 } 149 } 150 } 151 } 152 else if (dirin==4){ 153 if (yi<=1) return ; 154 for (int i=1;i<=2;i++) 155 for (int j=0;j<=3;j++) 156 { 157 int dir=pd34(j); 158 if (i==1){ 159 int yy=yi-1,xx=xi+zl[0][j],zz=zi+zl[1][j]; 160 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 161 vis[xx][yy][zz]=true; 162 dfs(dir,dirout,xx,yy,zz,used+1); 163 vis[xx][yy][zz]=false; 164 } 165 } 166 else{ 167 int yy=yi-2,xx=xi+zl[2][j],zz=zi+zl[3][j]; 168 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 169 vis[xx][yy][zz]=true; 170 dfs(dir,dirout,xx,yy,zz,used+1); 171 vis[xx][yy][zz]=false; 172 } 173 } 174 } 175 } 176 else if (dirin==5){ 177 if (zi>=z) return ; 178 for (int i=1;i<=2;i++) 179 for (int j=0;j<=3;j++) 180 { 181 int dir=pd56(j); 182 if (i==1){ 183 int zz=zi+1,xx=xi+zl[0][j],yy=yi+zl[1][j]; 184 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 185 vis[xx][yy][zz]=true; 186 dfs(dir,dirout,xx,yy,zz,used+1); 187 vis[xx][yy][zz]=false; 188 } 189 190 } 191 else{ 192 int zz=zi+2,xx=xi+zl[2][j],yy=yi+zl[3][j]; 193 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 194 vis[xx][yy][zz]=true; 195 dfs(dir,dirout,xx,yy,zz,used+1); 196 vis[xx][yy][zz]=false; 197 } 198 199 } 200 } 201 } 202 else if (dirin==6){ 203 if(zi<=1) return ; 204 for (int i=1;i<=2;i++) 205 for (int j=0;j<=3;j++) 206 { 207 int dir=pd56(j); 208 if (i==1){ 209 int zz=zi-1,xx=xi+zl[0][j],yy=yi+zl[1][j]; 210 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 211 vis[xx][yy][zz]=true; 212 dfs(dir,dirout,xx,yy,zz,used+1); 213 vis[xx][yy][zz]=false; 214 } 215 } 216 else{ 217 int zz=zi-2,xx=xi+zl[2][j],yy=yi+zl[3][j]; 218 if (xx>=1&&xx<=x&&yy>=1&&yy<=y&&zz>=1&&zz<=z&&!vis[xx][yy][zz]){ 219 vis[xx][yy][zz]=true; 220 dfs(dir,dirout,xx,yy,zz,used+1); 221 vis[xx][yy][zz]=false; 222 } 223 } 224 } 225 } 226 } 227 int main() 228 { 229 freopen("tube.in","r",stdin); 230 freopen("tube.out","w",stdout); 231 init(); 232 dfs(st,en,stx,sty,stz,0); 233 if (ans>6||can==false) cout<<"Impossible"; 234 else cout<<ans; 235 return 0; 236 }
第三题:压路机
一个矩阵图,每个节点和它的邻居(最多四个)由街道相连。每个街道恰好1 单位长。只要蒸汽压路机在经过某条街道之前或之后立即改变方向,它经过这条街道的实际耗时会变为估计值的2 倍。这种情况对于压路机从某个节点发动(比如Johnny 的起点)和到某个节点刹车(比如Johnny 的终点)也适用。
全部是9 的那条路看起来更加快捷。然而,因为加速和刹车的限制,每一条
边都需要2 倍的时间,这使得总时间达到108。由10 组成的路径更快,因为Johnny
可以在其中的两条路径上全速通过,即总用时100。
解:
写一个bfs。数组用一个维方向,两个数组,一个是直走后,一个是转弯后,遍历所有情况,找最小。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<string> 6 #include<queue> 7 #define maxn 105 8 #define M 12345678 9 using namespace std; 10 int R,C,ri,ci,rj,cj; 11 int mp[maxn][maxn][4],zhi[maxn][maxn][4],zhuan[maxn][maxn];//0 left,1 right,2 up,3 down 12 const int zl[2][4]={{0,0,-1,1},{-1,1,0,0}}; 13 struct pp{ 14 int x,y; 15 }; 16 bool vis[maxn][maxn]; 17 queue<pp> q; 18 void init() 19 { 20 cin>>R>>C>>ri>>ci>>rj>>cj; 21 for (int i=1;i<=R;i++) 22 { 23 for (int j=1;j<=C-1;j++) 24 { 25 scanf("%d",&mp[i][j][1]); 26 if (mp[i][j][1]==0) mp[i][j][1]=M; 27 mp[i][j+1][0]=mp[i][j][1]; 28 } 29 if (i<R) 30 for (int j=1;j<=C;j++) 31 { 32 scanf("%d",&mp[i][j][3]); 33 if (mp[i][j][3]==0) mp[i][j][3]=M; 34 mp[i+1][j][2]=mp[i][j][3]; 35 } 36 } 37 for(int i=1;i<=R;i++) 38 for(int j=1;j<=C;j++) 39 { 40 for(int k=0;k<=3;k++) 41 zhi[i][j][k]=zhi[i][j][k]=M; 42 zhuan[i][j]=M; 43 } 44 for (int i=0;i<4;i++) 45 zhi[ri][ci][i]=0; 46 zhuan[ri][ci]=0; 47 } 48 void bfs() 49 { 50 pp st; 51 st.x=ri;st.y=ci; 52 q.push(st); 53 vis[st.x][st.y]=true; 54 while (!q.empty()){ 55 pp suf=q.front(); 56 q.pop();vis[suf.x][suf.y]=false; 57 for (int i=0;i<=3;i++) 58 { 59 pp cur; 60 cur.x=suf.x+zl[0][i];cur.y=suf.y+zl[1][i]; 61 if (cur.x<=0||cur.x>R) continue; 62 if (cur.y<=0||cur.y>C) continue; 63 int last_dir=i^1; 64 int now=zhi[suf.x][suf.y][last_dir]+mp[suf.x][suf.y][i]; 65 if ((cur.x!=rj||cur.y!=cj)&&(suf.x!=ri||suf.y!=ci))//起点,终点要加、减速 66 { 67 if (now<zhi[cur.x][cur.y][last_dir]){ 68 zhi[cur.x][cur.y][last_dir]=now; 69 vis[cur.x][cur.y]=true;q.push(cur); 70 } 71 } 72 now=min(zhuan[suf.x][suf.y],zhi[suf.x][suf.y][last_dir])+mp[suf.x][suf.y][i]*2; 73 if (now<zhi[cur.x][cur.y][last_dir]){ 74 zhi[cur.x][cur.y][last_dir]=now; 75 vis[cur.x][cur.y]=true;q.push(cur); 76 } 77 if (now<zhuan[cur.x][cur.y]){ 78 zhuan[cur.x][cur.y]=now; 79 vis[cur.x][cur.y]=true;q.push(cur); 80 } 81 } 82 } 83 } 84 int main() 85 { 86 freopen("roller.in","r",stdin); 87 freopen("roller.out","w",stdout); 88 init(); 89 bfs(); 90 int ans=M; 91 for (int i=0;i<=3;i++) 92 ans=min(ans,zhi[rj][cj][i]); 93 ans=min(zhuan[rj][cj],ans); 94 if (ans==M) cout<<"Impossible"; 95 else cout<<ans; 96 return 0; 97 }