Noip模拟79 2021.10.17(题目名字一样)
T1 F
缩点缩成个$DAG$,然后根据每个点的度数计算期望值
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 #include<algorithm> 6 #define int long long 7 using namespace std; 8 namespace AE86{ 9 #define fuck cout<<"fuck"<<endl 10 #define out(x) cout<<#x<<"="<<x<<endl 11 inline int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 15 }inline void write(int x,char opt='\n'){ 16 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 17 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 18 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 19 }using namespace AE86; 20 const int NN=1005,mod=998244353; 21 int n,ans,deg[NN];char s[NN]; bool vis[NN]; 22 struct SNOW{int to,next;}e[1000005]; int head[NN],rp; 23 inline void add(int x,int y){e[++rp]=(SNOW){y,head[x]};head[x]=rp;} 24 inline void dfs(int x){ 25 if(vis[x])return;vis[x]=1;++deg[x]; 26 for(int i=head[x];i;i=e[i].next) dfs(e[i].to); 27 } 28 inline int qmo(int a,int b,int ans=1){ 29 int c=mod;for(;b;b>>=1,a=a*a%c)if(b&1)ans=ans*a%c; 30 return ans; 31 } 32 namespace WSN{ 33 inline short main(){ 34 freopen("f.in","r",stdin);freopen("f.out","w",stdout); 35 n=read(); 36 for(int i=1;i<=n;i++){ scanf("%s",s+1); 37 for(int j=1;j<=n;j++) if(s[j]=='1') add(i,j); 38 }for(int i=1;i<=n;i++) memset(vis,0,sizeof(vis)),dfs(i); 39 for(int i=1;i<=n;i++) ans=(ans+qmo(deg[i],mod-2))%mod; 40 write(ans); 41 return 0; 42 } 43 } 44 signed main(){return WSN::main();}
T2 S
发现每次考试的$T2$就是考人品的。。。
我爆搜加特判拿了四十,过程艰难,甚至想码一个线段树水分(但失败了)
有的人直接拿哈希扫,扫到一个答案加一个就拿了$90$,非常不服,但是。。。
cty:人家考场上就是敢码,人家就是敢交,你没那个勇气,所以你没那个分
确实是这样啊。。。。(叹~)
所以你知道了,哈希扫一遍加上特判一个测试点就可以做到$21ms$切掉这道大水题,因为数据是随的。。。
好了说暴(正)力(解),
不难想到需要冻龟(其实很难,我就是因为发现写冻龟数组开不下就没往哪里想,果不其然$Arbiter$上测的一车$AC$的内存全炸了)
但是$OJ$上能过,因为算的动态内存,而且是$MiB$
说一下内存的计算,$256MiB!=256MB$,$1MiB=1024\times 1024 B,1MB=1000 \times 1000 B$
好了,我们设$dp[i][j]$表示处理到$S$的$i$位,与$T$匹配了$j$位的最小字符删除数。
其实和$GT$考试很像
然后预处理一个$trans[i]['ch']$表示$S$和$T$匹配了$i$位时,下一个字符是$ch$,那么算上这个字符后$S$和$T$匹配了多少位
然后分情况讨论,
$s[i+1]==t[j+1]$
$dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)$这是删除一个字符的情况
$dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+1)$这是不删除的情况
$s[i+1]!=t[j+1]$
$dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)$删除
$dp[i+1][trans[j][s[i+1]]]=min(dp[i+1][trans[j][s[i+1]]],dp[i][j])$不删除
然后你会发现,数组开不下,但是不慌,对了就交就过了,实际上可以滚,但是我不会
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 namespace AE86{ 8 #define fuck cout<<"fuck"<<endl 9 #define out(x) cout<<#x<<"="<<x<<endl 10 inline int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 14 }inline void write(int x,char opt='\n'){ 15 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 16 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 17 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 18 }using namespace AE86; 19 const int NN=8003; 20 int n,m,nxt[NN],trans[NN][27],f[NN][NN]; 21 char s[NN],t[NN]; 22 inline void kmp(){ 23 nxt[1]=0; 24 for(int i=2,j=0;i<=m;++i){ 25 while(j&&t[i]!=t[j+1]) j=nxt[j]; 26 if(t[i]==t[j+1]) ++j; 27 nxt[i]=j; 28 } 29 for(int i=0;i<m;++i){ 30 for(int ch='a';ch<='z';++ch){ 31 int j=i; 32 while(j&&t[j+1]!=ch) j=nxt[j]; 33 if(t[j+1]==ch) ++j; 34 trans[i][ch-'a']=j; 35 } 36 } 37 } 38 inline void cmin(int &a,int b){a<b?(a=a):(a=b);} 39 namespace WSN{ 40 inline short main(){ 41 freopen("s.in","r",stdin);freopen("s.out","w",stdout); 42 scanf("%s%s",s+1,t+1);n=strlen(s+1);m=strlen(t+1);kmp(); 43 memset(f,0x3f,sizeof(f)); f[1][0]=0; 44 for(int i=1;i<=n;++i){ 45 for(int j=0;j<m;++j)if(f[i][j]<1e9){ 46 if(s[i]!=t[j+1]){ 47 cmin(f[i+1][trans[j][s[i]-'a']],f[i][j]); 48 cmin(f[i+1][j],f[i][j]+1); 49 }else{ 50 if(j+1<m) cmin(f[i+1][j+1],f[i][j]); 51 cmin(f[i+1][j],f[i][j]+1); 52 } 53 } 54 } 55 int ans=0x3fffffff; 56 for(int i=0;i<m;++i)ans=min(ans,f[n+1][i]); 57 write(ans); 58 return 0; 59 } 60 } 61 signed main(){return WSN::main();}
T3 Y 他的真名:[Noip2013]华容道
整的挺像$Fate$,不要在意博主二次元就好了
非常神仙的图论题,鉴于是看的别人的详细题解,这里直接给出链接了,不想看我叨叨的看这个更加详细的,戳这里
只说一下比较神仙的地方,就是这道题的图是以每个状态为点,花费为边建图
定义
指定的棋子为$S$
空白的格子为$E$
目标的格子为$T$
设状态$(i,j,k)$表示$S$在$(i,j)$,$E$格子在$(i,j)$的$k$方向,用$0,1,2,3$表示左、右、下、上
然后因为初始图上每个点的状态不变可以预处理,然后每次询问跑最短路。
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 namespace AE86{ 8 #define fuck cout<<"fuck"<<endl 9 #define out(x) cout<<#x<<"="<<x<<endl 10 inline int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 14 }inline void write(int x,char opt='\n'){ 15 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 16 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 17 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 18 }using namespace AE86; 19 const int NN=35,MM=200010,inf=1061109567; 20 int n,m,q,g[NN][NN]; 21 int dx[5]={-1,1,0,0}, 22 dy[5]={0,0,-1,1}; 23 struct SNOW{int to,val,next;}e[MM];int head[MM],rp; 24 inline void add(int x,int y,int z){e[++rp]=(SNOW){y,z,head[x]};head[x]=rp;} 25 26 struct node{int x,y;};node E,S,T; 27 queue<node> Q; 28 int dis[NN][NN]; 29 inline void bfs(int ex,int ey,int sx,int sy,int pos){ 30 memset(dis,0,sizeof(dis)); 31 Q.push(node{ex,ey}); dis[ex][ey]=1; 32 while(!Q.empty()){ 33 node now=Q.front();Q.pop(); 34 for(int i=0;i<4;i++){ 35 int X=now.x+dx[i],Y=now.y+dy[i]; 36 if(!g[X][Y]||dis[X][Y]||(X==sx&&Y==sy)) continue; 37 dis[X][Y]=dis[now.x][now.y]+1; Q.push(node{X,Y}); 38 } 39 } 40 if(pos==4) return; 41 for(int i=0;i<4;i++){ 42 int X=sx+dx[i],Y=sy+dy[i]; 43 if(!dis[X][Y]||(X==ex&&Y==ey)) continue; 44 add(sx*30*4+sy*4+pos,sx*30*4+sy*4+i,dis[X][Y]-1); 45 } 46 add(sx*30*4+sy*4+pos,ex*30*4+ey*4+(pos^1),1); 47 } 48 int dit[MM]; 49 queue<int> qaq; 50 bool vis[MM]; 51 inline void spfa(int sx,int sy){ 52 memset(dit,0x3f,sizeof(dit)); 53 memset(vis,0,sizeof(vis)); 54 for(int i=0;i<4;i++){ 55 if(!dis[sx+dx[i]][sy+dy[i]]) continue; 56 int sta=sx*30*4+sy*4+i; 57 qaq.push(sta);vis[sta]=true;dit[sta]=dis[sx+dx[i]][sy+dy[i]]-1; 58 } 59 while(!qaq.empty()){ 60 int x=qaq.front(); qaq.pop(); vis[x]=false; 61 for(int i=head[x];i;i=e[i].next){ 62 int y=e[i].to; 63 if(dit[y]>dit[x]+e[i].val){ 64 dit[y]=dit[x]+e[i].val; 65 if(!vis[y]) vis[y]=true,qaq.push(y); 66 } 67 } 68 } 69 } 70 #define wsn 71 // #define mzs 72 namespace WSN{ 73 inline short main(){ 74 #ifdef mzs 75 freopen("in.in","r",stdin); 76 #endif 77 #ifdef wsn 78 freopen("y.in","r",stdin); freopen("y.out","w",stdout); 79 #endif 80 n=read(); m=read(); q=read(); 81 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) g[i][j]=read(); 82 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) 83 if(g[i][j]) for(int k=0;k<4;k++) 84 if(g[i+dx[k]][j+dy[k]]) bfs(i+dx[k],j+dy[k],i,j,k); 85 while(q--){ 86 E.x=read();E.y=read();S.x=read();S.y=read();T.x=read();T.y=read(); 87 if(S.x==T.x&&S.y==T.y){puts("0");continue;} 88 bfs(E.x,E.y,S.x,S.y,4);spfa(S.x,S.y); int ans=inf; 89 for(int i=0;i<4;i++) ans=min(ans,dit[T.x*30*4+T.y*4+i]); 90 if(ans==inf) puts("-1");else write(ans); 91 } 92 return 0; 93 } 94 } 95 signed main(){return WSN::main();}
T4 O
好吧,见过拉格朗日插值,没见过拉个朗日插值,所以咕咕咕
蒟蒻刚学会扫描线。。。