Timstamp:2023/07/23 02:40 原本想說寫一寫就去睡了,結果被卡常弄了好久 QQ 這題我自己寫出來的複雜度是 $10^8$ 很危。 一開始想說使用 bfs 的方式,有需要轉移再推進 queue,結果因為 queue 的關係大卡常。 :::spoiler TLE 的程式碼 ```cpp= int ary[10010]; int vis[110][110]; int n,m,k; pii move(pii now,int dis,int way){ if(way==1){ int nx = now.F+dis; nx%=n; return {nx,now.S}; } if(way==2){ int nx = now.F-dis; nx%=n; nx = (nx+n)%n; return {nx,now.S}; } if(way==3){ int nx = now.S+dis; nx%=m; return {now.F,nx}; } if(way==4){ int nx = now.S-dis; nx%=m; nx = (nx+m)%m; return {now.F,nx}; } return {0,0}; } signed main(){ AC cin>>n>>m; int x,y,s,t; cin>>x>>y>>s>>t; cin>>k; rep1(i,k)cin>>ary[i]; queue<pii> q; q.push({x,y}); int cc = 1; while(q.size()&&cc<=k){ int qz = q.size(); rep1(j,qz){ pii tp = q.front(); q.pop(); for(int i=1;i<=4;i++){ pii np = move(tp,ary[cc],i); if(vis[np.F][np.S]==cc+1){ continue; } else{ vis[np.F][np.S] = cc+1; q.push(np); } } } cc++; } if(!vis[s][t]){ no; } else{ yes; } } ``` ::: 後來想說就不用 BFS 了,直接看有沒有被轉移(上一輪有被走過) 結果還是被卡常 :::spoiler TLE again ```cpp= #define getchar getchar_unlocked inline void input(int &_x) { _x = 0; int _tmp = 1; char _tc = getchar(); while((_tc < '0' || _tc > '9') && _tc != '-') _tc = getchar(); if(_tc == '-') _tc = getchar(), _tmp = -1; while(_tc >= '0' && _tc <= '9') _x = _x*10+(_tc-48), _tc = getchar(); _x *= _tmp; } int ary[10010]; int vis[2][110][110]; int n,m,k; inline pii move(pii now,int dis,int way){ if(way==1){ int nx = now.F+dis; nx%=n; return {nx,now.S}; } if(way==2){ int nx = now.F-dis; nx%=n; nx = (nx+n)%n; return {nx,now.S}; } if(way==3){ int nx = now.S+dis; nx%=m; return {now.F,nx}; } if(way==4){ int nx = now.S-dis; nx%=m; nx = (nx+m)%m; return {now.F,nx}; } return {0,0}; } signed main(){ // AC // cin>>n>>m; input(n),input(m); int x,y,s,t; // cin>>x>>y>>s>>t; input(x),input(y),input(s),input(t); // cin>>k; input(k); // rep1(i,k)cin>>ary[i]; rep1(i,k)input(ary[i]); vis[1][x][y] = 1; for(int cc=1;cc<=k;cc++){ rep(i,n){ rep(j,m){ if(vis[cc%2][i][j]==cc){ pii tp = {i,j}; for(int c=1;c<=4;c++){ pii np = move(tp,ary[cc],c); vis[1-cc%2][np.F][np.S] = cc+1; } } } } } if(vis[1-k%2][s][t]!=k+1){ no; } else{ yes; } } ``` ::: 最後去看了大神的程式碼後,我發現他很多地方都用位元運算取代模運算,還有加減乘除。 於是我把裡面的一些模運算弄掉,用成一樣的做法,結果就AC了! 我自己實驗了一下,因為大概是 $10^8$ 次的模運算,分別繳交了兩次,時間竟然差了五倍!!! 第一次被卡常的經驗 get XD 我也學到教訓了 (接近TLE) ![](https://hackmd.io/_uploads/B1KQNsYc3.png) (取代模運算) ![](https://hackmd.io/_uploads/HJmVViYcn.png) :::spoiler AC! ```cpp= signed main(){ // AC // cin>>n>>m; input(n),input(m); int x,y,s,t; // cin>>x>>y>>s>>t; input(x),input(y),input(s),input(t); // cin>>k; input(k); // rep1(i,k)cin>>ary[i]; rep1(i,k)input(ary[i]); vis[0][x][y] = 1; #define add(x,y,n) ( x+y<n?x+y:x+y-n ) #define del(x,y,n) ( x-y>=0?x-y:x-y+n ) for(int cc=1;cc<=k;cc++){ rep(i,n){ rep(j,m){ int d1 = ary[cc],d2 = d1%m; d1 %= n; vis[cc&1][i][j] = vis[(cc-1)&1][add(i,d1,n)][j] | vis[(cc-1)&1][del(i,d1,n)][j] | vis[(cc-1)&1][i][add(j,d2,m)] | vis[(cc-1)&1][i][del(j,d2,m)] ; } } } if(!vis[k&1][s][t]){ no; } else{ yes; } } ``` :::