【CF1043D】Mysterious Crime(贡献)

题意:给定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 }

原文地址:https://www.cnblogs.com/myx12345/p/9872409.html