Peter有一个字符串s=s1s2...sn, 令suffi=sisi+1...sn是s第i字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀ai=lcp(suffi,suffi+1)(1≤i<n). 现在给你数组a, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对109+7取模的结果即可.
乍一看以为是水题,判断一下a[i]是否为0不就可以了吗,不为0的话乘上25即可。结果发现这题根本不是坑你怎么算个数,而是坑你什么时候输出0……
一个小时wa了9次我也是醉了,就这样与div1擦肩而过……
下面仔细说下思路:假设如果a[i]=5,那么毫无疑问正确的字符串应该满足a[i+1]=4,a[i+2]=3.......因此以sum=26为底数,每次碰上a[i]!=0 往后跳即可(也可以直接跳过多个位置直接到达下一个a[i]=0的位置),若碰上a[i]=0,则乘上25。
以上为字符串符合正确的情况下的结果,而错误情况包括:a[i]>0而后续a[i+1]等未逐一递减至0;a[i]+i>n,即超过字符串长度。
做题过程中莫名其妙的以为a[i]只能递减至0,之后必须为0,实际上存在如4 3 2 1 0 3 2 1 0这样的a[i]排列组合,而不是一连串的0。明白这些,很快就A了。
#include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cstdlib> #include <string> #include <vector> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define INF 0x3f3f3f3 const int N=100005; const int mod=1e9+7; int a[N]; long long sum=0; int main(){ int t,n; cin>>t; while (t--) { a[0]=INF; sum=26; cin>>n; for (int i=1; i<=n-1; i++) { scanf("%d",&a[i]); } int flag=1; for (int i=1; i<=n-1; i++) { if (a[i]+i>n) { flag=0; break; } if (a[i]>=a[i-1]&&a[i]&&a[i-1]) { flag=0; break; } } for (int i=2; i<=n-1; i++) { if (a[i-1]-a[i]!=0) { for (int j=i; j<=i-2+a[i-1]; j++) { if (a[j-1]-a[j]!=1) { flag=0; break; } } } } int i=1; while (i<=n-1) { if (a[i]==0) { sum*=25; sum%=mod; } i++; } if (flag) cout<<sum<<endl; else cout<<"0"<<endl; } return 0; }
之后m个询问,询问包含2个点。输出在i=1-m个询问中,2个点之间的距离*i,对1e9+7取模。
昨晚做的时候第一题把我错麻木了,看题没什么思路,想着无脑最短路才发现n,m高达1e5,最后无奈没A。
最后看官方题解,简洁到无情,拿6个点建图floyd算完之后,复杂度居然是O(6^2*m),当时懵逼后想了想也没什么具体思路。
最后想出来贴切题解的的是将题中3条边的6个点进行floyd最短路计算,计算完毕后,假设询问的两个点为a和b,则假设a到b的过程中必经过6个点中任意一个,那么找到a到该点的最短路与b到该点的最短路,两者相加即可。而计算最短路时其实就是对6个点进行枚举,枚举必经过每一个点的过程。假设必经过6个点中的A,用之前floyd算出来的6个点最短路找到a点与b点到A点最短路(如先去B,由B到A等等,每个点计算6次,即达到6^2*m的复杂度。
做题时以为输入是a1,a2,a3,b1,b2,b3的顺序,还很好奇为什么输入顺序这么奇怪,wa了一小时发现是a1,b1……之后又发现计算最短路过程中忘记了a到b有可能不经过任意一点直接计算abs(b-a)即可。最后艰难的a了。
#include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cstdlib> #include <string> #include <vector> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define INF 0x3f3f3f3 const int N=100005; const int mod=1e9+7; int d[10][10],a[10]; int s[N],t[N]; long long sum=0; int main(){ int ti,n,m; cin>>ti; while (ti--) { sum=0; memset(d, 0, sizeof(d)); cin>>n>>m; for (int i=1; i<=3; i++) { cin>>a[i]>>a[i+3]; } for (int i=1; i<=m; i++) { scanf("%d %d",&s[i],&t[i]); } d[1][4]=d[4][1]=1; d[2][5]=d[5][2]=1; d[6][3]=d[3][6]=1; for (int i=1; i<=6; i++) { for (int j=1; j<=6; j++) { if (d[i][j]==0) { d[i][j]=abs(a[i]-a[j]); } } } for (int k=1; k<=6; k++) { for (int i=1; i<=6; i++) { for (int j=1; j<=6; j++) { if (d[i][j]>d[i][k]+d[k][j]) { d[i][j]=d[i][k]+d[k][j]; } } } } int d1,d2,mind; for (int k=1; k<=m; k++) { mind=abs(s[k]-t[k]); for (int i=1; i<=6; i++) { d1=abs(s[k]-a[i]); d2=abs(t[k]-a[i]); for (int j=1; j<=6; j++) { if (i==j) { continue; } d1=min(d1, abs(a[j]-s[k])+d[j][i]); d2=min(d2, abs(a[j]-t[k])+d[j][i]); } if (d1+d2<mind) { mind=d1+d2; } } sum+=((long long)k*mind)%mod; sum%=mod; } cout<<sum<<endl; } return 0; }