D. Mysterious Crime

链接

[http://codeforces.com/contest/1043/problem/D]

题意

给你一个m*n的矩阵(m<=10,n<=1e5),
每一行的数字是1到n里不同的数字
问你这m行中有多少个公共子序列

分析

用一个二维数组保存每一行的每个位置的数字的前面一个数字是什么,
然后后面用最后一行的数字和前面每一行对比,统计就好了,具体看代码就很容易理解了
还有一个组合数学的东西看下面图片就好了

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
int a[N];
ll sum[N];
int pre[12][N];
int main(){
    int n,m,i,j;
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        memset(sum,0,sizeof(sum)); 
        for(i=1;i<=m;i++)
        for(j=1;j<=n;j++){
            scanf("%d",&a[j]);//因为重复使用a[],所以最后存的是最后一行的值 
          if(j>1) pre[i][a[j]]=a[j-1];//第存的是i行a[j]这个数字的前面一个数字 
        }
        ll ans=n;
        for(i=2;i<=n;i++){//只需要从第二个列的数字开始就可以了,因为第一个数字前面没有数字 
         int cnt=0;
            for(j=1;j<m;j++)
                if(pre[j][a[i]]==pre[m][a[i]])
                cnt++;
            if(cnt==m-1) sum[i]+=sum[i-1]+1;//如果所有行都有公共的部分就可以加了
            //sum[i]+=sum[i-1]+1和组合数学有关,你可以想n个单位矩形挨在一起,
            //问你总共有多少个矩形是同一个问题就是个递推 
            ans+=sum[i];
        }
        printf("%lld\n",ans); 
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mch5201314/p/9940280.html