文件名:road.cpp(pas)ios
時間限制:1s算法
空間限制:512MB數組
題目描述:ide
給出1個 N 個點的有向圖,每一個點的出度剛好爲一。spa
如今但願給這 N 條邊重定向,求圖中不出現環的方案數(對 109 + 7 取模)。code
輸入格式:blog
第一行一個正整數 N。ci
第二行 N 個正整數 Xi,表示存在一條有向邊 i 指向 Xi。字符串
輸出格式:get
一行,一個整數 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; }
給出兩個僅有小寫字母組成的字符串 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)。 算法思想 一、定義dp [i][j]:表示字符串序列A的前i個字符組成的序列Ax和字符串序列B的前j個字符組成的序列By之間的最長 公共子序列L(i,j )的長度(m ,n分別爲Ax和By的長度,i<=m,j<=n) 二、若是Ax [i] =By [j],那麼Ax與By之間的最長公共子序列L( i,j )的最後一項必定是這個元素, 因此dp [i][j] = dp[i-1][j-1] + 1。 三、若是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] )。 四、初始值爲:dp[0][j] = dp[i][0] = 0. 五、題意要求求出任意一個最長公共子序列,這點要如何實現呢? 仍然考慮上面的遞推式,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]時根據來源進行不一樣的標記,回溯就能夠找到一個最長公共子序列。 */
#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; }
給出一個二階魔方,保證 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; }