目录
A.Alive Fossils
H.Insert 1, Insert 2, Insert 3, ...
I.Make It Square
J.Permutation and Primes
A.Alive Fossils
思路:一开始题意看半天没看懂,后面发现只需要输出t组输入中,都出现过的字符串即可。
代码:
void solve() {int t;cin>>t;for(int i=1;i<=t;i++){int n;cin>>n;for(int i=1;i<=n;i++){string s;cin>>s;mp[s]++;}}vector<string>ans;for(auto x:mp){if(x.second==t){ans.push_back(x.first);}}cout<<ans.size()<<endl;for(auto x:ans) cout<<x<<endl;
}
H.Insert 1, Insert 2, Insert 3, ...
思路:根据题意我们可以发现,因为数字是按顺序1,2,3......插,所以若一段区间[l,r]满足条件,那么[l,r'](r'<=r)也必然满足条件。我们可以从后往前遍历,也就是遍历区间[i,n](i从n遍历到1)。每次遍历到a[i]时,因为插入是顺序的,所以这个a[i],一定能和a[i]+1这个值对应,把它“抵消”掉,所以若一个区间合法,那么这个区间会被“抵消”完,第i个点的贡献为最左边的没被抵消完的端点-i。
举个例子吧,拿样例一来说,它的序列为:
1 1 2 2 3 3
从后往前遍历,遍历了i=5以及i=6,此时存入了两个3,它们都不合法:
不合法的值:3 3
不合法的下标:5 6
贡献为:最左边的没被抵消完的端点-i=5-5=0
然后遍历到i=4,此时a[i]=2,他能与一个a[i]+1抵消,也就是把3给抵消了,此时:
不合法的值:2 3
不合法的下标:4 6
贡献为:最左边的没被抵消完的端点-i=4-4=0
然后遍历到i=3,此时a[i]还是2,他还是能把3抵消,此时:
不合法的值:2 2
不合法的下标:3 4
贡献为:最左边的没被抵消完的端点-i=3-3=0
然后遍历到i=2,此时a[i]是1,他能把一个2抵消,此时:
不合法的值:2 (1不放入不合法的值中,因为单个1合法)
不合法的下标:4
贡献为:最左边的没被抵消完的端点-i=4-2=2
然后遍历到i=1,此时a[i]还是1,他能把一个2抵消,此时:
不合法的值: 无(1不放入不合法的值中,因为单个1合法)
不合法的下标:无
此时后面都合法了,贡献为i~n整个区间也就是6
总贡献为 :0+0+0+2+6=8
代码:
vector<int>ans,pos[maxn];
//ans存最入不满足条件的点
//pos[x]存入a[i]=x的位置
int a[maxn],st[maxn];
void solve() {int n,res=0;cin>>n;ans.push_back(n+1);//放入初始值,使得:若点i后面没有不满足条件的点,则答案加n-i+1,也就是i~n区间的贡献。for(int i=1; i<=n; i++)cin>>a[i];for(int i=n; i>=1; i--) {if(pos[a[i]+1].size()) {st[pos[a[i]+1].back()]=true;//这个点被上一个点"抵消"了,标记这个点已经合法了pos[a[i]+1].pop_back();//消掉}if(a[i]>1) {pos[a[i]].push_back(i);//存入值对应的下标ans.push_back(i);//存入不合法的位置}while(st[ans.back()])ans.pop_back();//把合法的都弹出res+=ans.back()-i;}cout<<res<<endl;
}
I.Make It Square
思路:若字符串s的长度小于t,我们将两个字符串翻转后交换,仍可以使得字符串s大于t,所以我们考虑s长度大于t的情况。
通过手玩样例我们可以发现,随着字符串p和q长度的增加,对于字符串s,分割点是固定的,分割点在后缀大小为(s.size()-t.size())/2。举个例子,比如样例三:
s=abbabbababbab,t=bab。
当p.size()=q.size()=1时:
p+s+q+t=?abbabbababbab?bab
分割为 ?abbabbab abbab?bab
当p.size()=q.size()=2时:
p+s+q+t=??abbabbababbab??bab
分割为 ??abbabbab abbab??bab
以??abbabbab abbab??bab举例,
首先,若bab与abbabbab的后缀不重合,那么这两个部分的字符串怎么都不会相等。然后可以看出,我们可以通过字符串abbabbab作为后缀,字符串abbab作为前缀,来求出已经不固定的字符个数。
若这两个部分有重合,则判断重合部分是否一样,也就是abbabbab的重合前缀和abbab重合后缀是否一样,利用z函数判断即可,若重合部分一样则答案为1,反之答案为0。
若这两个部分没重合,则计算不固定字符的个数,答案为26的幂次。
具体实现见代码:
代码:
vector<int> zFunction(string s) {int n = s.size();vector<int> z(n + 1);z[0] = n;for (int i = 1, j = 1; i < n; i++) {z[i] = max(0ll, min(j + z[j] - i, z[i - j]));while (i + z[i] < n && s[z[i]] == s[i + z[i]]) {z[i]++;}if (i + z[i] > j + z[j]) {j = i;}}return z;
}
void solve() {k26[0]=1;for(int i=1; i<maxn; i++) {k26[i]=k26[i-1]*26%mod;}//预处理26的幂次string s,t;int n;cin>>n>>s>>t;int lens=s.size(),lent=t.size();if((lens+lent)%2) {//若字符串长度之和为奇数,那么它们怎么都不能分割成两个相等字符串for(int i=1; i<=n; i++)cout<<0<<" ";return;}if(lens<lent) {reverse(s.begin(),s.end());reverse(t.begin(),t.end());swap(s,t);swap(lens,lent);}if(s.substr((lens+lent)/2-lent,lent)!=t) {//判断字符串t作为后缀是否合法for(int i=1; i<=n; i++)cout<<0<<" ";return;}auto v=zFunction(s);reverse(v.begin(),v.end());//v[i]表示长度为i的后缀与前缀的最大公共前缀FOR(1,n) {int now=(lens+lent+2*i)/2;//当前一半的总字符串长度int p=abs(lens-now);if(lens>now) {//若有重合部分if(v[p]!=p) cout<<0<<" ";//重合部分是否全部相同else cout<<1<<" ";//答案为加1} else {cout<<k26[p]<<" ";//答案为26^(不确定字符的个数)}}
}
J.Permutation and Primes
思路:我们可以先构造长度为7的循环节:
i+3,i+6,i+1,i+4,i+7,i+2,i+5
那么若n%7不为0的时候怎么办呢?我们可以先把前面的长度为7循环节给赋值,然后最后7+n%7个数,我们随便找一组解满足它与循环节的末尾形成奇质数,放预处理后面即可。
代码:
int cmp[7][15] {{3,6,1,4,7,2,5},//长度为7的循环节{5,2,7,4,1,8,3,6},//最后8个数,此时n%7=1{9,6,3,8,5,2,7,4,1},//最后9个数,此时n%7=2{9,4,7,2,5,10,3,8,1,6},//最后10个数,此时n%7=3{11,8,5,10,7,2,9,4,1,6,3},//最后11个数,此时n%7=4{1,6,3,10,7,12,5,2,9,4,11,8},//最后12个数,此时n%7=5{1,4,9,2,7,12,5,10,3,6,13,8,11}//最后13个数,此时n%7=6
};
void solve() {cin>>n;int k=n/7;if(n==2) {cout<<"1 2"<<endl;} else if(n==3) {cout<<"1 2 3"<<endl;} else if(n==4) {cout<<"1 2 3 4"<<endl;} else if(n==5) {cout<<"1 4 3 2 5"<<endl;} else if(n==6) {cout<<"4 3 6 5 2 1"<<endl;}if(n<=6)return;for(int i=0; i<k-1; i++) {for(int j=0; j<7; j++) {a[i*7+j+1]=i*7+cmp[0][j];}}//前面的循环节赋值 for(int i=0; i<7+n%7; i++) {a[(k-1)*7+i+1]=(k-1)*7+cmp[n%7][i];}//最后放合法解 for(int i=1; i<=n; i++)cout<<a[i]<<" \n"[i==n];
}