2018 1.21测试

  套路

文件名:road.cpp(pas)ios

时间限制:1s算法

空间限制:512MB数组

题目描述:ide

  给出1个 N 个点的有向图,每一个点的出度刚好为一。spa

  如今但愿给这 N 条边重定向,求图中不出现环的方案数(对 109 + 7 取模)。code

输入格式:blog

  第一行一个正整数 Nci

  第二行 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;
}
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

 输出格式:

一行,一个整数,表示 str str的最长公共子序列的长度。

样例读入:

abdcba abafdsfa

样例输出:

4

样例解释:

若是字符串从开始标号,能够验证 fang = f0; 1; 2; 5gfbng = 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]时根据来源进行不一样的标记,回溯就能够找到一个最长公共子序列。

*/   
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 个整数,按上图的顺序依次给出 CiCi 2 f1; 2; 3; 4; 5; 6g

输出格式:

一行,t 个用空格隔开的正整数,表示复原的最小字典序操做序列,要求< 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),(17),故字典序最小的为 (2)

数据范围:

对于 20% 的数据,保证 N = 1

对于 40% 的数据,保证 N<=

对于另 20% 的数据,保证 N <=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姓大佬代码
相关文章
相关标签/搜索