题意:给定m个人,每个人有n个数字且每个人的所有数字都是一个n的排列,求有多少种方案去掉某个前缀和后缀后m个人剩余的部分相等
m<=10,n<=1e5
思路:考虑极长的一段连续匹配的串,因为最后需要是连续的一段,所以它对答案的贡献应该是它的子串个数
刚开始以为是子序列个数还傻乎乎的去写高精了,也算是一个教训吧
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<queue> 9 #include<vector> 10 #include<ctime> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 #define N 110000 21 #define M 130 22 #define MOD 1000000007 23 #define eps 1e-8 24 #define pi acos(-1) 25 26 int a[11][N],b[11][N],n,m; 27 28 int isok(int x,int y) 29 { 30 //if(x==0) return 1; 31 for(int i=2;i<=m;i++) 32 if(b[i][x]!=b[i][y]-1) return 0; 33 return 1; 34 } 35 36 37 int main() 38 { 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=m;i++) 41 for(int j=1;j<=n;j++) 42 { 43 scanf("%d",&a[i][j]); 44 b[i][a[i][j]]=j; 45 } 46 a[1][0]=0; 47 ll ans=0; 48 ll len=1; 49 for(int i=2;i<=n;i++) 50 if(isok(a[1][i-1],a[1][i])) len++; 51 else 52 { 53 //printf("len=%lld ",len); 54 ans+=(len+1)*len/2; 55 len=1; 56 } 57 //printf("len=%lld ",len); 58 ans+=(len+1)*len/2; 59 60 printf("%lld ",ans); 61 return 0; 62 }