P1884 COW
分析:
方法一:
前缀和预处理
- 记录C和W的个数
- 前缀和分别记录当前位置以及当前位置之前C和W的个数
- 遍历到字母O,用O左边C的个数*右边W的个数即为COW出现的次数
- 分别从C左边所有O中选一个和C右边所有W选一个组合,即为O左边C的个数乘O右边个数(排列组合中的乘法原理)
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
string str;
long long int a[100000+10];
long long int b[100000+10];
long long int aa[100000+10];
long long int bb[100000+10];
int main()
{
cin>>n;
cin>>str;
for(int i=0;i<n;i++)
{
if(str[i]=='C')
a[i]++;
else if(str[i]=='W')
b[i]++;
}
// for(int i=0;i<n;i++)
// cout<<b[i]<<" ";
// cout<<endl;
//前缀和预处理
for(int i=0;i<n;i++)
{
aa[i]=a[i]+aa[i-1];//当前位置以及当前位置之前有几个C
bb[i]+=b[i]+bb[i-1];//当前位置以及当前位置之前有几个W
}
// cout<<aa[n-1]<<" "<<bb[n-1]<<endl;
long long int count=0;
for(int i=0;i<n;i++)
{
if(str[i]=='O')
{
count=count+(aa[i-1]*(bb[n-1]-bb[i]));
}
}
cout<<count<<endl;
}
方法二:
记忆化搜索
- 从前往后遍历字符串
- 如果遍历到O,它只会与前面的C组成CO,组成的CO的个数为C的个数和O的个数相加(排列组合中的加法原理),不需要管后面C的数量
- 如果遍历到W,它只会和前面的CO组成COW,不需要管后面CO的个数,所以在W的位置累加前面CO的个数即可
- 记录当前C,CO,COW的个数
#include<bits/stdc++.h>
using namespace std;
int n;
string str;
long int c=0;//C的数量
long int o=0;//O的数量
long int w=0;//W的数量
int main()
{
cin>>n;
cin>>str;
for(int i=0;i<n;i++)
{
if(str[i]=='C')
{
c++;
}
else if(str[i]=='O')
{
o+=c;
}
else if(str[i]=='W')
{
w+=o;
}
}
cout<<w<<endl;
}