A-
题目大意:将R序列用B字母分隔开,使得连续R序列最大长度最小。
方法: R长度除以B长度算出分割为几块R序列,R长度模B长度算出余多少个R,然后把余的R每次加一个加到R序列中。
代码:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,r,b;
cin>>n>>r>>b;
int x=r/(b+1);
int y=r%(b+1);
int cnt=0;
for(int i=1;i<=b+1;i++)
{
for(int j=1;j<=x;j++)
{
cnt++;
cout<<"R";
}
if(y)
{
cnt++;
cout<<"R";
y--;
}
if(cnt<n)
{
cout<<"B";
cnt++;
}
}
cout<<endl;
}
return 0;
}
B-
题目大意: 将1和0变换,变换k次,每次都可以让其中一位不变,问k次后最大的数是什么,并且要输出每位的不变次数
方法: 如果k为奇数,那么如果没有选定不变,每个数经过奇数次变化 还是 变化(和1异或);如果k为偶数,那么如果没有选定不变,每个数经过偶数次变化 最终是 不变。
然后我们从头到尾遍历,让这个01序列先尽可能的大。如果k足够多,那么我们能变换出全为1的序列(1111111111)(设还剩q次变换)然后将最后一位变换q次。;k不够多的话,我们能让前面的数全为1(111111xxxxxxxxx)。
显然,这样获得的变换后的序列,是最大的。
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=200010;
int f[N];//存储每一位的不变换的次数
int main()
{
int t;
cin>>t;
while(t--)
{
memset(f,0,sizeof f);
int n,k;
cin>>n>>k;
string a;
cin>>a;
if(k==0)
{
cout<<a<<endl;
for(int i=1;i<=n;i++)
{
cout<<0<<' ';
}
cout<<endl;
}else
{
int ed=a.size()-1;
if(k%2)
{
for(int i=0;i<=ed;i++)
{
if(a[i]=='1')
{
if(k)
{
k--;
f[i]=1;
}else
{
a[i]='0';
}
}else
{
a[i]='1';
}
}
if(k&&k%2)
{
if(a[ed]=='1')
{
a[ed]='0';
}else
{
a[ed]='1';
}
}
f[ed]+=k;
}else
{
for(int i=0;i<=ed;i++)
{
if(a[i]=='0')
{
if(k)
{
k--;
a[i]='1';
f[i]=1;
}
}
}
if(k&&k%2)
{
if(a[ed]=='1')
{
a[ed]='0';
}else
{
a[ed]='1';
}
}
f[ed]+=k;
}
cout<<a<<endl;
for(int i=0;i<=ed;i++)
{
cout<<f[i]<<' ';
}
cout<<endl;
}
}
return 0;
}
C-
题目大意: 顺序的攻打X1到Xn,可以迁都到攻打后的城池,问总花费是多少
方法: 贪心。但是不能只考虑现在待攻打的城池,因为迁都后,影响了后续所有待攻打的城池。所以如下图:
注意:全部开longlong,否则会溢出。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=200010;
LL x[N];
void solve(void)
{
LL n,a,b;
scanf("%lld %lld %lld",&n,&a,&b);
LL res=0;
LL cap=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&x[i]);
}
res+=x[1]*b;
for(int i=2;i<=n;i++)
{
if((n-i+1)*b>a)
{
res+=(x[i-1]-x[cap])*a;
cap=i-1;//capital
}
res+=(x[i]-x[cap])*b;
}
printf("%lld\n",res);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}