D题因为一些小错误又FST了
TA:Three swimmers
题意:有三个游泳的人分别会在0,a,2a,3a,…,0,b,2b,3b,…,以及0,c,2c,3c的时刻位于游泳场的最左端.现在你在p时刻站在泳池最左端,问最快多久之后,会有一个人游到最左端.
idea:模一模就出答案了,注意模完为零的情况就好
ACcode:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
LL t,a,b,c,p,aa,bb,cc,ans;
int main()
{
cin>>t;
while(t--)
{
scanf("%lld %lld %lld %lld",&p,&a,&b,&c);
aa = (a - ( p%a ))%a;
bb = (b - ( p%b ))%b;
cc = (c - ( p%c ))%c;
ans = min( min( aa,bb ) , cc );
printf("%lld\n",ans);
}
return 0;
}
TB:Card Deck
题意:题目大意为给定一个排列,每次可以将末尾k个数取出并按照原顺序拼接另一个数列,使得另一个数列的字典序最大
idea:因为要求字典序最大,所以每一步的策略即为将前面未选取的数中的最大值放置在最前面,维护一个当前前n项中的最大值t。先从大到小(用结构体记录原来的位置)排序,从最大值开始定位输出当前位置到末尾的数,接着看下一个的位置。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define MIN 0xc0c0c0c0
#define INF 0x3f3f3f3f
#define N 101000
using namespace std;
int t,n,a[N],maxx,last;
struct node
{
int val,xu;
}b[N];
bool cmp(node x,node y)
{
return x.val>y.val;
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>t;
while(t--)
{
a[0] = MIN;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i].val = a[i];
b[i].xu = i;
}
sort(b+1,b+n+1,cmp);
last = n;
for(int i=1;i<=n;i++)
{
if( b[i].xu <= last )
{
for(int j=b[i].xu;j<=last;j++)
{
printf("%d ",a[j]);
}
last = b[i].xu-1;
}
}
cout<<endl;
}
return 0;
}
TC:Maximum width
题意:给出两个字符串S和T,问S中与T相同的子序列在S中的相邻字母的间隔的最大值。
idea:正向遍历一遍T,求出T的每个字母在S中出现的坐标的最小值,再反向遍历一遍T,求出当前情况下能在S中出现的最大值,最后计算一个字母能在S中出现的最小位置和下一个字母能在S中出现的最大位置之间的差值,结果取最大即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define N 1001000
#define INF 0x3f3f3f3f
using namespace std;
int n,m,ans,i,j;
char s[N],t[N];
int a[N],b[N];
int main()
{
ans = 0;
scanf("%d %d",&n,&m);
scanf("%s %s",&s+1,&t+1);
cout<<s;
int p = n;
for(i=1,j=1;i<=m;i++)
{
while( t[i] != s[j] ) j++;
if( t[i] == s[j] )
{
a[i] = j;
j++;
}
}
for(i=m,j=n;i>=1;i--)
{
while( t[i] != s[j] ) j--;
if( t[i] == s[j] )
{
b[i] = j;
j--;
}
}
for(i=1;i<m;i++)
{
ans = max( b[i+1] - a[i] , ans );
}
cout<<ans;
return 0;
}
TD:Genius’s Gambit
题意:给定数a,b,k,要求求出两个数x,y,使得x与y在二进制下的0的个数为a,1的个数为b,且x-y在二进制下1的个数为k。不存在这样的x和y就输出No.
idea:比较显然,先特判a=1和b=0这两个情况,此情况下k>0就输出No,不然就输出0。然后考虑x-y后最后还能剩下几个1,推一推会发现最后剩下(a+b-2)个1,判断一下k符不符合要求,符合要求的话,x和y的第一位一定是1,然后y的最后一位一定是1,x的从最后一位倒推的第k位一定是1,剩下的1按顺序放就好,不过这部分的1在x和y的位置一定要相同(这样才能抵消)。
ACcode:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define N 1001000
#define INF 0x3f3f3f3f
using namespace std;
int a,b,k,maxx,bb,len;
char s[N],t[N];
int main()
{
cin>>a>>b>>k;
if( a==0 || b==1 )
{
maxx = 0;
}
else
{
maxx = (b-1+a)-1;
}
if( k > maxx )
{
cout<<"No";
return 0;
}
len = a+b;
for(int i=1;i<len;i++)
{
s[i] = '0';
t[i] = '0';
}
s[0] = '1';
t[0] = '1';
if( b>1 ) t[len-1] = '1';
if( b>1 ) s[len-1 - k] = '1';
bb = b-2;
for(int i=1;i<len;i++)
{
if( s[i]!='1' && t[i]!='1' )
{
if( bb>0 )
{
bb--;
s[i] = '1';
t[i] = '1';
}
}
}
cout<<"Yes"<<endl;
cout<<s<<endl;
cout<<t;
return 0;
}