2017北京国庆刷题Day5 afternoon
期望得分:100+60+100=260
实际得分:0+60+40=100
设图中有m个环,每个环有si条边,有k条边不在环中
ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)…… *( 2^sm -2)* 2^k
(环上的边只有两种可能形成环)
找环好找,怎么找树?
一种方法是tarjan找出所有的环,总边数-环的边数=树的边数
std用了拓扑排序
考场上忘了树的情况,爆零了。
注意:n个点n条边是环套树森林
#include<cstdio> #define N 100001 using namespace std; typedef long long LL; int to[N],d[N],q[N],sum; const int mod=1e9+7; LL pow(LL a,int b) { LL res=1; for(;b;b>>=1,a=a*a%mod) if(b&1) res=res*a%mod; return res; } void dfs(int x) { sum++; d[x]=0; if(d[to[x]]) dfs(to[x]); } int main() { freopen("road.in","r",stdin); freopen("road.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&to[i]),d[to[i]]++; int h=1,t=0; for(int i=1;i<=n;i++) if(!d[i]) q[++t]=i; while(h<=t) { if(!(--d[to[q[h]]])) q[++t]=to[q[h]]; ++h; } LL ans=pow(2,t); for(int i=1;i<=n;i++) if(d[i]) { sum=0; dfs(i); ans=ans*(pow(2,sum)-2)%mod; } printf("%I64d",ans); }
本题60分是经典的n^2 LCS问题
第一个串长1000,第二个串长1e6
很显然枚举只能枚举第一个串
n^2 中是dp[i][j] 表示第一个字符串的前i个字符 与 第二个字符串的前j个字符 的 最长公共子串长度
它的优化是:
dp[i][j] 表示 第一个字符串的前i个字符,与 第二个字符串匹配了长为j的最长公共子串,第j个字符在第二个字符串中的最左下标
这样最后倒序枚举 j,当dp[len1][j]<=len2 时,输出j,return 0
如何转移?
考虑顺推
第一个字符串的第i+1 位如果不发生匹配,那么dp[i+1][j]=min(dp[i+1][j],dp[i][j])
第i+1位如果发生匹配,那么dp[i+1][j+1]=min(dp[i+1][j+1],nxt[dp[i][j]+1][s1[i+1]])
其中nxt[i][j]表示在第二个字符串中,第i位及后面最早出现字符j的位置
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 1001 #define M 1000001 char s1[N],s2[M]; int nxt[M][26],dp[N+2][N]; int main() { freopen("lcs.in","r",stdin); freopen("lcs.out","w",stdout); scanf("%s%s",s1+1,s2+1); int len1=strlen(s1+1),len2=strlen(s2+1); for(int i=0;i<26;i++) nxt[len2+1][i]=len2+5; for(int i=len2;i>=0;i--) for(int j=0;j<26;j++) if(s2[i]-'a'==j) nxt[i][j]=i; else nxt[i][j]=nxt[i+1][j]; memset(dp,63,sizeof(dp)); for(int i=0;i<=len1;i++) dp[i][0]=0; for(int i=0;i<len1;i++) for(int j=0;j<=i && dp[i][j]<=len2;j++) { dp[i+1][j]=min(dp[i+1][j],dp[i][j]); if(j<len1) dp[i+1][j+1]=min(dp[i+1][j+1],nxt[dp[i][j]+1][s1[i+1]-'a']); } for(int i=len1;i>=0;i--) if(dp[len1][i]<=len2) { printf("%d\n",i); return 0; } }
60分暴力:
#include<cstdio> #include<cstring> #include<algorithm> #define N 1001 using namespace std; char s1[N],s2[N]; int l1,l2; int dp[N][N]; int main() { freopen("lcs.in","r",stdin); freopen("lcs.out","w",stdout); scanf("%s%s",s1+1,s2+1); l1=strlen(s1+1); l2=strlen(s2+1); for(int i=1;i<=l1;i++) for(int j=1;j<=l2;j++) if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); printf("%d",dp[l1][l2]); }
题面修改:后面的DEF分别改为CBA
首先很关键的一点:
因为要求操作字典序最小,所以DEF没有用
例如:下面转90相当于上面转270
然后 大模拟
考场上复制时漏改一个数组,丢了60分o(╥﹏╥)o
#include<cstdio> #include<algorithm> using namespace std; int n,tmp[10]; int ans[10]; int L[2][2],R[2][2],U[2][2],D[2][2],F[2][2],B[2][2]; bool ok; bool judge(int sum) { if(!(L[0][0]==L[0][1] && L[0][1]==L[1][0] && L[1][0]==L[1][1])) return false; if(!(R[0][0]==R[0][1] && R[0][1]==R[1][0] && R[1][0]==R[1][1])) return false; if(!(U[0][0]==U[0][1] && U[0][1]==U[1][0] && U[1][0]==U[1][1])) return false; if(!(D[0][0]==D[0][1] && D[0][1]==D[1][0] && D[1][0]==D[1][1])) return false; if(!(F[0][0]==F[0][1] && F[0][1]==F[1][0] && F[1][0]==F[1][1])) return false; if(!(B[0][0]==B[0][1] && B[0][1]==B[1][0] && B[1][0]==B[1][1])) return false; for(int i=1;i<=sum;i++) ans[i]=tmp[i]; ans[0]=sum; return true; } void self90(int k[2][2],int a1,int a2,int b1,int b2,int c1,int c2,int d1,int d2) { int t=k[a1][a2]; k[a1][a2]=k[b1][b2]; k[b1][b2]=k[c1][c2]; k[c1][c2]=k[d1][d2]; k[d1][d2]=t; } void other90(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { int t=k1[a1][a2]; k1[a1][a2]=k2[b1][b2]; k2[b1][b2]=k3[c1][c2]; k3[c1][c2]=k4[d1][d2]; k4[d1][d2]=t; a2^=1; b2^=1; c2^=1; d2^=1; t=k1[a1][a2]; k1[a1][a2]=k2[b1][b2]; k2[b1][b2]=k3[c1][c2]; k3[c1][c2]=k4[d1][d2]; k4[d1][d2]=t; } void other90_(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { int t=k1[a1][a2]; k1[a1][a2]=k2[b1][b2]; k2[b1][b2]=k3[c1][c2]; k3[c1][c2]=k4[d1][d2]; k4[d1][d2]=t; a1^=1; b1^=1; c1^=1; d1^=1; t=k1[a1][a2]; k1[a1][a2]=k2[b1][b2]; k2[b1][b2]=k3[c1][c2]; k3[c1][c2]=k4[d1][d2]; k4[d1][d2]=t; } void other90_3(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { int t=k1[a1][a2]; k1[a1][a2]=k2[b1][b2]; k2[b1][b2]=k3[c1][c2]; k3[c1][c2]=k4[d1][d2]; k4[d1][d2]=t; } void self180(int k[2][2],int a1,int a2,int b1,int b2,int c1,int c2,int d1,int d2) { swap(k[a1][a2],k[b1][b2]); swap(k[c1][c2],k[d1][d2]); } void other180(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { swap(k1[a1][a2],k2[b1][b2]); swap(k3[c1][c2],k4[d1][d2]); a2^=1; b2^=1; c2^=1; d2^=1; swap(k1[a1][a2],k2[b1][b2]); swap(k3[c1][c2],k4[d1][d2]); } void other180_(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { swap(k1[a1][a2],k2[b1][b2]); swap(k3[c1][c2],k4[d1][d2]); a1^=1; b1^=1; c1^=1; d1^=1; swap(k1[a1][a2],k2[b1][b2]); swap(k3[c1][c2],k4[d1][d2]); } void other180_3(int k1[2][2],int a1,int a2,int k2[2][2],int b1,int b2,int k3[2][2],int c1,int c2,int k4[2][2],int d1,int d2) { swap(k1[a1][a2],k2[b1][b2]); swap(k3[c1][c2],k4[d1][d2]); } void dfs(int x,char ty) { if(ok) return; if(judge(x-1)) { ok=true; return; } if(x==n+1) return; if(ty!='A') { self90(U,0,0,1,0,1,1,0,1); other90(F,0,0,R,0,0,B,0,1,L,0,1); tmp[x]=1; dfs(x+1,'A'); if(ok) return; self90(U,0,0,0,1,1,1,1,0); other90(F,0,0,L,0,1,B,0,1,R,0,0); self180(U,0,0,1,1,0,1,1,0); other180(F,0,0,B,0,1,R,0,0,L,0,1); tmp[x]=2; dfs(x+1,'A'); if(ok) return; self180(U,0,0,1,1,0,1,1,0); other180(F,0,0,B,0,1,R,0,0,L,0,1); self90(U,0,0,0,1,1,1,1,0); other90(F,0,0,L,0,1,B,0,1,R,0,0); tmp[x]=3; dfs(x+1,'A'); self90(U,0,0,1,0,1,1,0,1); other90(F,0,0,R,0,0,B,0,1,L,0,1); if(ok) return; } if(ty!='B') { self90(L,0,0,0,1,1,1,1,0); other90_(F,0,0,U,0,0,B,1,0,D,1,0); tmp[x]=4; dfs(x+1,'B'); if(ok) return; self90(L,0,0,1,0,1,1,0,1); other90_(F,0,0,D,1,0,B,1,0,U,0,0); self180(L,0,0,1,1,0,1,1,0); other180_(F,0,0,B,1,0,U,0,0,D,1,0); tmp[x]=5; dfs(x+1,'B'); if(ok) return; self180(L,0,0,1,1,0,1,1,0); other180_(F,0,0,B,1,0,U,0,0,D,1,0); self90(L,0,0,1,0,1,1,0,1); other90_(F,0,0,D,1,0,B,1,0,U,0,0); tmp[x]=6; dfs(x+1,'B'); if(ok) return; self90(L,0,0,0,1,1,1,1,0); other90_(F,0,0,U,0,0,B,1,0,D,1,0); } if(ty!='C') { self90(F,0,0,1,0,1,1,0,1); other90_3(R,0,0,U,1,0,L,1,0,D,1,1); other90_3(R,1,0,U,1,1,L,0,0,D,1,0); tmp[x]=7; dfs(x+1,'C'); if(ok) return; self90(F,0,0,0,1,1,1,1,0); other90_3(R,0,0,D,1,1,L,1,0,U,1,0); other90_3(R,1,0,D,1,0,L,0,0,U,1,1); self180(F,0,0,1,1,0,1,1,0); other180_3(R,0,0,L,1,0,U,1,0,D,1,1); other180_3(R,1,0,L,0,0,U,1,1,D,1,0); tmp[x]=8; dfs(x+1,'C'); if(ok) return; self180(F,0,0,1,1,0,1,1,0); other180_3(R,0,0,L,1,0,U,1,0,D,1,1); other180_3(R,1,0,L,0,0,U,1,1,D,1,0); self90(F,0,0,0,1,1,1,1,0); other90_3(R,0,0,D,1,1,L,1,0,U,1,0); other90_3(R,1,0,D,1,0,L,0,0,U,1,1); tmp[x]=9; dfs(x+1,'C'); if(ok) return; self90(F,0,0,1,0,1,1,0,1); other90_3(R,0,0,U,1,0,L,1,0,D,1,1); other90_3(R,1,0,U,1,1,L,0,0,D,1,0); } } int main() { freopen("cube.in","r",stdin); freopen("cube.out","w",stdout); scanf("%d",&n); scanf("%d%d%d%d",&U[0][0],&U[0][1],&U[1][0],&U[1][1]); scanf("%d%d%d%d",&F[0][0],&F[0][1],&F[1][0],&F[1][1]); scanf("%d%d%d%d",&L[0][1],&L[0][0],&L[1][1],&L[1][0]); scanf("%d%d%d%d",&R[0][0],&R[0][1],&R[1][0],&R[1][1]); scanf("%d%d%d%d",&D[1][0],&D[1][1],&D[0][0],&D[0][1]); scanf("%d%d%d%d",&B[1][0],&B[1][1],&B[0][0],&B[0][1]); dfs(1,'G'); for(int i=1;i<=ans[0];i++) printf("%d ",ans[i]); return 0; }