A:http://codeforces.com/contest/1400/problem/A
解析:
发现每一个字符串,都包含s[n-1],所以直接打印n个s[n-1]即可
#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
int answ[maxn];
int md[maxn];
int b[maxn];
int n,m;
int a[maxn];
int v[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string s;
cin>>s;
for(int i=1;i<=n;i++)
cout<<s[n-1];
cout<<endl;
}
}
B:http://codeforces.com/contest/1400/problem/B
题意:
两个袋子大小:p,f
两种物品数量:c1,c2
两种物品所占空间:s,w
求能装的最大数量
解析:
贪心来讲,规定s<w,那么对于第一个袋子,尽量先放s,然后w,第二个袋子也是如此
根据这个贪心思路,可以对第一个袋子拿取的s数量进行枚举,s装好,再装w。c1,c2去掉之前的消耗,再对第二个袋子进行同样操作。
细节在注释里
#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
ll p,f;
ll c1,c2,s,w;
cin>>p>>f>>c1>>c2>>s>>w;
ll maxx=0; //这里并没有交换s,w,第一个袋子虽然应该优先装小的,但是下面的for已经枚举到了第一种袋子的所有可能
for(int i=0;i<=min(c1,p/s);i++)
{
ll s1,s2,s3;//i,s1为第一个袋子分别装s,w的数量。s2,s3分别为第二个袋子装s,w的数量
s1=(p-s*i);
s1=min(s1/w,c2);
if(s<=w) //第二个袋子优先选小
{
if(f>=(c1-i)*s) //还能再装s
{
s2=c1-i;
s3=min(c2-s1,(f-(c1-i)*s)/w);
}
else
{
s2=f/s;
s3=0;
}
}
else
{
if(f>=(c2-s1)*w)//还能再装w
{
s2=c2-s1;
s3=min(c1-i,(f-(c2-s1)*w)/s);
}
else
{
s2=0;
s3=f/w;
}
}
maxx=max(maxx,i+s1+s2+s3);
}
cout<<maxx<<endl;
}
}
C:http://codeforces.com/contest/1400/problem/C
题意:
给出字符串s和整数x,求字符串w
s满足:
w[i+x]或w[i-x]为1,si为1,否则si为0
解析:
初始化w全为1。
遍历si的'0',把w[i]变成符合对应要求
再次遍历si的'1',如果w[i+x]==0&&w[i-x]==0,输出-1
#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int x;
cin>>s1>>x;
int le=strlen(s1);
for(int i=0;i<le;i++)
s2[i]='1';
for(int i=0;i<le;i++)
{
if(s1[i]=='0')
{
if(i>=x)
s2[i-x]='0';
if(i+x<le)
s2[i+x]='0';
}
}
int ok = 0;
for(int i=0;i<le;i++)
{
int ok1=0,ok2=0;
if(s1[i]=='1')
{
if(i>=x&&s2[i-x]=='1')
ok1=1;
if(i+x<le&&s2[i+x]=='1')
ok2=1;
if(!ok1&&!ok2)
{
ok=1;break;
}
}
}
if(ok)
cout<<"-1"<<endl;
else
{
for(int i=0;i<le;i++)
cout<<s2[i];
cout<<endl;
}
}
}
D:http://codeforces.com/contest/1400/problem/D
题意:
数组ai,1<=i<j<k<l<=n,求ai=ak,aj=al的数量
解析:
枚举j,l。
假设aj==al
....aj....ax.....al,要想凑够满足题意的那四个,需要aj之前存在与ax相等的数,有几个,就能和aj,al凑成几个。所以就需要记录aj之前出现了几个ax
cnt[]记录aj之前的各个数字出现的次数。
要注意一下顺序问题,cnt[]是要在for的最后更新才行。
#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=3e3+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
int a[maxn];
ll cnt[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(cnt,0,sizeof(cnt));
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
ll sum = 0 ;
for(int j=1;j<n;j++)
{
int md=0;
for(int l=j+1;l<=n;l++)
{
if(a[j]==a[l])
sum+=md;
md+=cnt[a[l]];
}
cnt[a[j]]++;
}
cout<<sum<<endl;
}
}
E:http://codeforces.com/contest/1400/problem/E
题意:
给出数组
操作1:[L,R]集体减1
操作2:对任意一个数,把它变成比它自己小的任意一个数
把所有数归0的最小操作数
解析:
分治
之前做过。
[L,R]都变0的话,需要r-l+1步,
与集体减1那个操作取个min就可以了
#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=5e3+10;
const int maxn2=1e9+10;
const int mod=1e9+10;
char s1[maxn],s2[maxn];
ll a[maxn];
ll cnt[maxn];
struct node
{
int x1,y1,x2,y2;
}st[maxn];
int ac(int l,int r)
{
if(l>r) return 0;
int minn=mod;
int k;
for(int i=l;i<=r;i++)
{
if(a[i]<minn)
{
minn=a[i];
k=i;
}
}
int md=a[k];
for(int i=l;i<=r;i++)
a[i]-=minn;
return min(r-l+1,md+ac(l,k-1)+ac(k+1,r));
}
int sum=0;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
cout<<ac(1,n)<<endl;
// cout<<sum<<endl;