套路
文件名:road.cpp(pas)
时间限制:1s
空间限制:512MB
题目描述:
给出1个 N 个点的有向图,每个点的出度恰好为一。
现在希望给这 N 条边重定向,求图中不出现环的方案数(对 109 + 7 取模)。
输入格式:
第一行一个正整数 N。
第二行 N 个正整数 Xi,表示存在一条有向边 i 指向 Xi。
输出格式:
一行,一个整数 Ans,表示定向后不出现环的方案数。
样例读入:
5
2 3 1 5 4
样例输出:
12
数据范围:
对于 30% 的数据,保证 N 20 对于 60% 的数据,保证 N 1000 对于 100% 的数据,保证 N 105
tarjan+组合数学
先tarjan求强连通分量,然后对于强两连分量里面的每一条边我们可以进行正反两种翻转方法,如果一个强连通分量里面有n个点,那么就有n^2种方式,但是注意到出现环的这种情况下我们要减去2,为什么?因为我们要考虑到把这些边全部翻转过来以及都不翻转的时候存在环,那么这种情况就可以直接减去了,然后对于不同种环我们直接让他们相乘就好了(利用乘法原理),然后我们考虑到存在父边的情况,这种情况下,这条边可正可反,那么就是两种情况我们直接ans*2就好了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 101000 #define LL long long #define mod 1000000007 using namespace std; LL ans;bool vis[N]; int n,x,y,s,tim,top,sum,tot; int to[N],dfn[N],low[N],head[N],stack[N],nextt[N],belong[N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } int add(int x,int y) { tot++; to[tot]=y; nextt[tot]=head[x]; head[x]=tot; } int tarjan(int x) { low[x]=dfn[x]=++tim; stack[++top]=x;vis[x]=true; for(int i=head[x];i;i=nextt[i]) { int t=to[i]; if(vis[t]) low[x]=min(low[x],dfn[t]); else if(!dfn[t]) tarjan(t),low[x]=min(low[x],low[t]); } if(low[x]==dfn[x]) { sum++,belong[sum]++; for(;stack[top]!=x;top--) { int t=stack[top]; vis[t]=false; belong[sum]++; } top--,vis[x]=false; } } LL qpow(int a,LL b) { LL res=1; while(b) { if(b&1) res=res*a%mod; b>>=1;a=1ll*a*a%mod; } return res-2; } int main() { freopen("road.in","r",stdin); freopen("road.out","w",stdout); n=read();s=ans=1; for(int i=1;i<=n;i++) x=read(),add(x,i); for(int i=1;i<=n;i++) if(!dfn[i]) { tarjan(i); for(int j=s;j<=sum;j++) if(belong[j]>1) ans=ans*qpow(2,belong[j])%mod; else ans=ans*2%mod; s=sum+1; } printf("%I64d",ans); return 0; }
AC代码
exLCS
文件名:lcs.cpp(pas)
时间限制:1s
空间限制:512MB
题目描述:
给出两个仅有小写字母组成的字符串 str1 和 str2,试求出两个串的最长公共子序列。公共子序列定义如下:
若有 a1 < a2 < < ak 和 b1 < b2 < < bk,满足
str1[ai] = str2[bi]; 8i 2 f1; 2; 3; ; kg;
则称找到了一个长度为 k 的公共子序列。
输入格式:
第一行一个字符串 str1。第二行一个字符串 str2。
输出格式:
一行,一个整数,表示 str1 与 str2 的最长公共子序列的长度。
样例读入:
abdcba abafdsfa
样例输出:
4
样例解释:
如果字符串从 0 开始标号,可以验证 fang = f0; 1; 2; 5g,fbng = f0; 1; 4; 7g 是满足要求的方案。
数据范围:
对于 10% 的数据,保证 jstr1j 10; jstr2j 10 对于 30% 的数据,保证 jstr1j 20; jstr2j 30
对于 60% 的数据,保证 jstr1j 1000; jstr2j 1000 对于 100% 的数据,保证 jstr1j 1000; jstr2j 106
60分lcs朴素dp
f[i][j]=f[i-1][j-1]+1;(if(a[i]==b[j]) i表示a字符串匹配到第i位,j表示b字符串匹配到第j位
f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1]));
/*最大公共子序列问题 在解决最长公共子序列(LCS)问题,即求字符串A,B的公共子序列LCS(注意:LCS不一定连续,但和原始序列的元素顺序有关)中长度最长的公共子序列时,因为最长公共子序列不唯一,但是最长公共子序列长度是一定的,所以先把问题简化,如何求两个序列的最长公共子序列长度? 我们首先想到的肯定是暴力枚举法。 先来看看:假设序列A有n 个元素,序列B有 m 个元素,那么A,B分别有2^n,2^m个子序列,如果任意两个子序列一一比较,比较的的子序列高达2^(m+n)对,这还没有算具体的复杂度。 所以我们可以试试动态规划,把这个问题分解成子问题:求A的前i个元素和B的前j个元素之间的最长公共子序列长度。这时的空间复杂度为o(m+n)。 算法思想 1、定义dp [i][j]:表示字符串序列A的前i个字符组成的序列Ax和字符串序列B的前j个字符组成的序列By之间的最长 公共子序列L(i,j )的长度(m ,n分别为Ax和By的长度,i<=m,j<=n) 2、如果Ax [i] =By [j],那么Ax与By之间的最长公共子序列L( i,j )的最后一项一定是这个元素, 所以dp [i][j] = dp[i-1][j-1] + 1。 3、如果Ax[i] != By[j],设LCS(i-1,j-1)是L( i -1, j-1 )的最后一个元素,或者L(i-1,j-1)是空序列, 则 t!= Ax[i]和t!=By[j]至少有一个不成立。 (1) 当 LCS(i-1,j-1) != Ax[i] 时,dp[i][j]= dp[i-1][j]; (2) 当 LCS(i-1,j-1) != By[j] 时,ap[i][j]= dp[i][j-1]; 所以dp[i][j]= max ( dp[i-1][j],dp[i][j-1] )。 4、初始值为:dp[0][j] = dp[i][0] = 0. 5、题意要求求出任意一个最长公共子序列,这点要如何实现呢? 仍然考虑上面的递推式,L(i,j)的最后一个元素LCS( i,j )的来源有三种情况,定义数组flag[MAXN][MAXN]用 以标记来的方向: (1) dp[i][j] = dp[i-1][j-1] + 1,对应字符LCS( i-1,j-1)接上LCS( i,j),flag[i][j] = 1,表示从斜向上 左方来; (2) dp[i][j] = dp[i-1][j],对应字符LCS(i-1,j)接上LCS(i,j),flag[i][j] = 2,表示从上方过来; (3) dp[i][j] = dp[i][j-1],对应字符LCS(I,j-1)接上LCS(i,j),flag[i][j] = 3,表示从左方过来。 我们只要在计算dp[i][j]时根据来源进行不同的标记,回溯就可以找到一个最长公共子序列。 */
lcs讲解
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 1010 using namespace std; char a[N],b[N]; int l1,l2,f[N][N],ans; int main() { freopen("lcs.in","r",stdin); freopen("lcs.out","w",stdout); cin>>a+1>>b+1; l1=strlen(a+1),l2=strlen(b+1); for(int i=1;i<=l1;i++) for(int j=1;j<=l2;j++) { if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1; f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1])); } ans=f[l1][l2]; printf("%d",ans); return 0; }
60代码
魔方
文件名:cube.cpp(pas)
时间限制:1s
空间限制:512MB
题目描述:
给出一个二阶魔方,保证 N 步以内能够还原。“还原” 被定义为每个面均为纯色。请给出,操作编号字典序最小,且不存在同类操作相邻,的还原方案。
C1 |
C2 |
|||||
顶面 |
||||||
C3 |
C4 |
|||||
C9 C10 C5 |
C6 C13 C14 |
|||||
左面 |
前面 |
右面 |
||||
C11 |
C12 |
C7 |
C8 |
C15 C16 |
||
C17 |
C18 |
|||||
C1 |
C2 |
底面 |
||||
C19 |
C20 |
|||||
C3 |
C4 |
|||||
C14 |
||||||
C5 |
C6 |
C13 |
C21 |
C22 |
||
C16 |
后面 |
|||||
C15 |
||||||
C7 |
C8 |
C23 |
C24 |
操作编号 |
操作类别 |
操作描述 |
操作编号 |
操作类别 |
操作描述 |
1 |
A |
顶面顺时针旋转 90? |
10 |
D |
右面顺时针旋转 90? |
2 |
A |
顶面顺时针旋转 180? |
11 |
D |
右面顺时针旋转 180? |
3 |
A |
顶面顺时针旋转 270? |
12 |
D |
右面顺时针旋转 270? |
4 |
B |
左面顺时针旋转 90? |
13 |
E |
后面顺时针旋转 90? |
5 |
B |
左面顺时针旋转 180? |
14 |
E |
后面顺时针旋转 180? |
6 |
B |
左面顺时针旋转 270? |
15 |
E |
后面顺时针旋转 270? |
7 |
C |
前面顺时针旋转 90? |
16 |
F |
底面顺时针旋转 90? |
8 |
C |
前面顺时针旋转 180? |
17 |
F |
底面顺时针旋转 180? |
9 |
C |
前面顺时针旋转 270? |
18 |
F |
底面顺时针旋转 270? |
表 1: 注: 此处某面的 “顺时针” 是指从魔方外部正视该面时的顺时针方向
输入格式:
第一行一个正整数 N,表示最多步数。
接下来 24 个整数,按上图的顺序依次给出 Ci,Ci 2 f1; 2; 3; 4; 5; 6g。
输出格式:
一行,t 个用空格隔开的正整数,表示复原的最小字典序操作序列,要求 0 < t <N。最后一个数后无空格。
数据保证输入魔方是打乱的。
注:(1,2,3) 虽然长度长于 (2,3),但字典序更小。
样例读入:
2
1 1 1 1
4 4 2 2
6 6 3 3
3 3 6 6
5 5 5 5
4 4 2 2
样例输出:
2
样例解释:
因为不能类别相同的操作相邻,所以只有 2 种操作方式可以在两步内复原此时的魔方:
(2),(17),故字典序最小的为 (2)。
数据范围:
对于 20% 的数据,保证 N = 1
对于 40% 的数据,保证 N<=3
对于另 20% 的数据,保证 N <=6,且保证答案只用到前 6 种操作对于 100% 的数据,保证 N <=7
大模拟??
据说很恶心、、、
#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; }
某X姓大佬代码
原文地址:https://www.cnblogs.com/z360/p/8325460.html