A-QAQ
题意:给一个长度为 N 的字符串S, 求S中不含相邻字符且长度为的"QAQ"子序列个数.
题解:把'Q'的个数做前缀和和后缀和处理,a[] 存储'Q'个数的前缀和,b[]存储'Q'个数后缀和,如果第i个字符是'A',那么这时的个数为a[i-2] * b[i+2],枚举每一个'A',求和即可.
#include <bits/stdc++.h>
using namespace std;
const int N=5e3+5;
char s[N];
int a[N],b[N];
typedef long long ll;
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++){
if(s[i]=='Q') a[i]=a[i-1]+1;
else a[i]=a[i-1];
if(s[n-i+1]=='Q') b[n-i+1]=b[n-i+2]+1;
else b[n-i+1]=b[n-i+2];
}
ll ans=0;
for(int i=3;i<=n-2;i++){
if(s[i]=='A') ans+=1ll*a[i-2]*b[i+2];
}
cout<<ans<<endl;
return 0;
}
tips:实际上可以不用预先计算前缀和,可以边处理边计算前缀和.
#include <bits/stdc++.h>
using namespace std;
const int N=5e3+5;
char s[N];
int b[N];
typedef long long ll;
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++){
if(s[n-i+1]=='Q') b[n-i+1]=b[n-i+2]+1;
else b[n-i+1]=b[n-i+2];
}
ll ans=0;
int cnt=(s[1]=='Q')+(s[2]=='Q');
for(int i=3;i<=n-2;i++){
if(s[i]=='A') ans+=1ll*(s[i-1]=='Q'?cnt-1:cnt)*b[i+2];
cnt+=s[i]=='Q';
}
cout<<ans<<endl;
return 0;
}
C-Buy Fruits
题意:给你一组n个数,是[0,n-1]的一个排列,记为a,让你输出一组n个数,也是[0,n-1]的一个排列,记为b.使得每一个a[i]+b[i]值在[1,n-1]内,且只有某一个数重复一次.
题解:瞎搞找了个规律. 如果n为奇数(除了1,),输出 -1(1输出 0),如果n为偶数,b[0]=1,b[n/2]=0,b[i]=n-i-i,b[n-i+1]=(n+1)-a[i].如n=4, b[] =1, 2, 0, 3.
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
int vis[N];
int main(){
int n;
cin>>n;
if(n==1){
printf("0\n");
return 0;
}
if(n&1){
puts("-1");
return 0;
}
else{
a[0]=1;
for(int i=1;i<=n/2;i++){
if(i*2==n) a[i]=0;
else{
a[i]=n-i-i;
a[n-i]=(n+1)-a[i];
}
}
}
for(int i=0;i<n;i++){
printf("%d%c",a[i],i==n-1?'\n':' ');
}
return 0;
}