C、小红的字符串中值
思路:归纳批量求贡献。枚举该字符在多少个字串出现过,同时有个规律见下图。
#include<bits/stdc++.h>
using namespace std;
int main(){
char chr;
long long cnt=0;
int n;
string s;
cin>>n>>chr>>s;
for(int i=0;i<n;i++){
if(s[i]==chr){
cnt+=min(i+1,n-i);//此处为关键
}
}
cout<<cnt;
return 0;
}
类似题目:定义一个字符串权值是包含“kou”字串的数量,求一个字符串所有连续子串的权值和
D、小红的数组操作
思路:模拟双链表,根据讲解可以使用map存储元素i的左右点,思路就根据双链表的操作思路进行。
不知道为什么可以过,使用样例的时候显示内存超限。
#include<bits/stdc++.h>
using namespace std;
//map:下标从-1e9到1e9的离散化数组
map<int,int>l,r;//l[i]代表左节点,r[i]代表右节点
typedef long long lo;
int main(){
int n;
lo op=-1e9-1,ed=1e9+1;//初始化,头的右边是尾,尾的右边是头
r[op]=ed;
l[ed]=op;
int q;
cin>>q;
while(q--){
int c;
cin>>c;
if(c==1){
int x,y;
cin>>x>>y;
int ll,rr;
if(y==0)//插入
{
ll=op,rr=r[op];
}
else{
ll=y,rr=r[y];
}
r[ll]=x;
l[x]=ll;
r[x]=rr;
l[rr]=x;
}
//删除
else{
int x;
cin>>x;
int ll=l[x],rr=r[x];
r[ll]=rr;
l[rr]=ll;
}
}
vector<int> ans;
for(int i=r[op];i!=ed;i=r[i])
{
ans.push_back(i);
}
cout<<ans.size()<<endl;
for(auto i:ans)
{
cout<<i<<" ";
}
return 0;
}
这个是想套模板用数组做,但是没有成功,放在这里有时间回来完善。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int m;
int e[N],l[N],r[N],idx;
void insert(int a,int x){
e[idx]=x;
l[idx]=a,r[idx]=r[a];
l[r[a]]=idx,r[a]=idx++;
}
void init(){
l[1]=0;
r[0]=1;
idx=2;
}
void remove(int a){
l[r[a]]=l[a];
r[l[a]]=r[a];
}
int main(){
int q;
cin>>q;
while(q--){
int c;
cin>>c;
if(c==1){
int x,y;
cin>>x>>y;
if(y!=0)
{
insert(y,x);
}else{
insert(0, x);
}
}
else {
int b;
cin>>b;
remove(b);
}
}
int count=0;
for(int i=r[0];i!=1;i=r[i]) cout<<e[i]<<' ';
return 0;
}
E、小红的子集取反
思路:01背包 +dp(典型)
//值域是-40000到40000
#include<bits/stdc++.h>
using namespace std;
int dp[202][80080];//根据值域,由于下标不能为负数所以是80000,偏移,下面也是。
//dp[i][j] 代表前i项,使得最终和为j的选择的元素数量最小值
int main(){
int n;
int i,j,x;
cin>>n;
memset(dp,0x3f,sizeof(dp));//初始化
dp[0][40000]=0;
for(i=1;i<=n;i++){
cin>>x;
for(j=0;j<=80000;j++){
if(j+x>=0&&j+x<=80000)dp[i][j]=min(dp[i][j],dp[i-1][j+x]);
if(j-x>=0&&j-x<=80000)dp[i][j]=min(dp[i][j],dp[i-1][j-x]+1);
}
}
if(dp[n][40000]<n)cout<<dp[n][40000];
else cout<< -1;
}
F、小红的连续段
思路:隔板法。题目可以转变为将x分为n个正整数,正整数和为x,有多少种情况。
组合数公式:C(n,m)=n!/(m!*(n-m)!)
#include<bits/stdc++.h>
using namespace std;
long long jiecheng[11010];
const int mod=1e9+7;
long long power(long long a,int b){
long long res=1;
while(b){
if(b&1)res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
int niyuan(int x)//逆元
{
return power(x,mod-2);
}
long long zuhe(int n,int m){
if(m<0||n-m<0)return 0;
return jiecheng[n]*niyuan(jiecheng[m])%mod*niyuan(jiecheng[n-m])%mod;
}
int main(){
int i;
jiecheng[0]=1;
for(i=1;i<=2000;i++){
jiecheng[i]=jiecheng[i-1]*i%mod;
}
int x,y;
cin>>x>>y;
for(i=1;i<=x+y;i++){
int ji=i/2+i%2,ou=i/2;//奇数位的话,头和尾是相同的会比不是头的多一位
cout<<(zuhe(x-1,ji-1)*zuhe(y-1,ou-1)+zuhe(y-1,ji-1)*zuhe(x-1,ou-1))%mod<<'\n';
}
return 0;
}