目录
A.Alive Fossils
H.Insert 1, Insert 2, Insert 3, ...
I.Make It Square
J.Permutation and Primes
思路:一开始题意看半天没看懂,后面发现只需要输出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]++;
}
}
vectorans;
for(auto x:mp){
if(x.second==t){
ans.push_back(x.first);
}
}
cout<
思路:根据题意我们可以发现,因为数字是按顺序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
代码:
vectorans,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<
思路:若字符串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 zFunction(string s) {
int n = s.size();
vector 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>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(lensnow) {//若有重合部分
if(v[p]!=p) cout<<0<<" ";//重合部分是否全部相同
else cout<<1<<" ";//答案为加1
} else {
cout<
思路:我们可以先构造长度为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"<