A-A
国际性大新闻,某国有5种兵种了。实力强悍,已经要撼动5常的地位了。
这五种兵种分别用’x’,‘t’,‘C’,‘p’,'c’来表示。现在某国正在进行国际性的阅兵。
阅兵队列呈一字排开,现在问你,这个阅兵队列中,有多少个"xtCpc"这样的子序列
Input
n (1<= n <= 2*10^5)
长度为n的字符串
Output
输出多少个子序列
Sample Input
10
xtCxtCpcpc
Sample Output
2
这题我WA了两次,第一次一层循环,五个if-else语句,果断WA,在审一次题,发现我想的太简单了,这个序列一定要按"xtCpc"的顺序,中间可以插一些别的字母,于是我写了一次五层循环的代码(居然没有时间超限!!)用了一个标记数组避免了时间超限的问题。
//ac代码,太乱了,无法直视
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char a[1000010];
int main()
{
int n;
int i,j,k,w,x;
while(cin>>n)
{
int ans=0;
scanf("%s",a);
int len=strlen(a);
int flag;
for(int i=0; i<len; i++)
{
if(a[i]==0)//最后改完加这个
continue;
if(a[i]=='x')//xxxx
{
flag=1;
a[i]=0;
//cout<<23<<" "<<i<<" ";
for(j=i+1; j<len; j++)
{
if(a[j]==0)//最后改完加这个
continue;
if(flag==0)
break;//cout<<23<<" ";
if(a[j]!='x'&&a[j]!='t')
a[j]=0;
else if(a[j]=='t')//ttttt
{
a[j]=0;
//cout<<23<<" ";
for(k=j+1; k<len; k++)
{
if(a[k]==0)//最后改完加这个
continue;
if(flag==0)
break;
if(a[k]!='x'&&a[k]!='t'&&a[k]!='C')
a[k]=0;
else if(a[k]=='C')//CCCCCC
{
a[k]=0;
for(w=k+1; w<len; w++)
{
if(a[w]==0)//最后改完加这个
continue;
if(flag==0)
break;
if(a[w]!='x'&&a[w]!='t'&&a[w]!='C'&&a[w]!='p')
a[i]=0;
else if(a[w]=='p')//ppppppp
{
a[w]=0;
for(x=w+1; x<len; x++)
{
if(a[x]==0)//最后改完加这个
continue;
if(a[x]!='x'&&a[x]!='t'&&a[x]!='C'&&a[x]!='p'&&a[x]!='c')
a[x]=0;
else if(a[x]=='c')//ccccccc
{
a[x]=0;
ans++;
flag=0;
break;
}
}
}
}
}
}
}
}
}
}
cout<<ans<<endl;
}
return(0);
}
测试完了之后发现其实也没必要这么麻烦写五个if-else就够了,可惜当时没想明白。
B-B
小明带领了k个幼儿园班级.
现在这里有n堆糖果
小明想通过下面两种操作使得最后每个班得到的糖果数,都一样多
一:将相邻的两队的糖果相加合并成一个新的糖果堆
二:将一个堆的糖果分成相邻的两堆,这两个堆的和仍然等于之前的堆
请问至少需要多少次操作才能将这n堆糖果,合并成k堆一样大小的糖果
Input
第一行是一个数t,代表有t组样例。(1≤T≤100)
每组样例的第一行是两个数n(1≤n≤105)和k(1≤k≤105)
接下来一行是n个数a0,a1,a2…an-1
Output
对于每组样例,输出的格式是 ‘Case #x: y’,x代表这是第几个case,从1开始,y是最少的操作次数,
如果不能将这n个数变成相等的k个数,则y为-1.
Sample Input
3
1 3
14
3 1
2 3 4
3 6
1 2 3
Sample Output
Case #1: -1
Case #2: 2
Case #3: 3
题目是说要把n堆糖果均分为k堆,只能通过合并俩堆糖或者将一堆糖一分为二。一共有两类情况;第一类可以通过看第一个样例得出,就是糖果的总和sum%k如果不等于0,就肯定不能均分的,所以输出-1;第二类情况就要遍历整个数组,先求平均数average,如果a[i]==average就跳过,如果a[i]<average,就把a[i]合并到下一堆里面,如果a[i]>average,就把a[i]分成大小为k的堆,剩下的合并到下一堆。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
long long a[100010],sum;
int main()
{
int n,k,t,flag=1;
cin>>t;
while(t--)
{
cin>>n>>k;
sum=0;
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
}
if(sum%k!=0)//第一类情况
{
printf("Case #%d: -1\n",flag++);
}
else
{
int ans=0;
long long average=sum/k;
for(int i=0;i<n;i++)
{
if(a[i]==average)
continue;
if(a[i]<average)
{
a[i+1]+=a[i];
ans++;//直接合并到下一堆
}
else if(a[i]>average)
{
if(a[i]%average==0)
{
ans=ans+a[i]/average-1;
}
else
{
a[i+1]+=a[i]%average;
ans=ans+a[i]/average+1;
}
}
}
printf("Case #%d: %d\n",flag++,ans);
}
}
}
C-C
今天幼儿园的小朋友们学了"+", “-”, “", “/“这四种运算,现在他们想用四种运算来生成一个数字。他们取一个只含有数字1到9的字符串,把字符串分成5个区间,然后依次添加四个运算”+”, “-”, "”, “/”,然后再计算结果(除法是整数除法).现在请你帮助他们取得最后结果的最大值
Input
第一行输入一个整数T,表示测试用例的数量。(1≤T≤100000)
每个测试都输入一行字符串,只包含数字“1”-“9”。5<=字符串长度<=20
Output
对于每个测试用例,您应该输出“case#x:y”,其中x表示用例号,y表示该组测试样例的答案。
Sample Input
1
12345
一开始我没看到依次添加这四个大字,测试完了才看清楚,虽然看清楚了也没什么luan用。题意就是把这个只包含数字的字符串拆开,从中扣四个空格出来然后填上加减乘除,求出最大值。
就是这样,要想让结果最大,那num1+num2就要大,而(num3*num4)/num5要小,所以可以得出num1~2里面必须有一个数只有个位,num3和num4都只有个位,剩下的都归num5,这样num3和num4得积就越小,而除数num5就越大。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int Min=-9999999;
int main()
{
char a[50];
int t,flag=1;
cin>>t;
while(t--)
{
scanf("%s",a);
int len=strlen(a);
long long num1,num2,sum,num3,num4,num5,Max;
Max=Min;
for(int i=2;i<len-2;i++)
{
num1=0;
for(int j=0;j<i-1;j++)
{
num1=num1*10+a[j]-'0';
}
num1+=a[i-1]-'0';//第一种分界,0~i-2 + i-1
num2=0;
for(int j=1;j<i;j++)
{
num2=num2*10+a[j]-'0';
}
num2+=a[0]-'0';//第二种分界,0 + 1~i-1
sum=max(num1,num2);//前两个数的和,为sum1和sum2的max
num3=a[i]-'0';//第一个乘数
num4=a[i+1]-'0'; //第二个乘数
num5=0;
for(int j=i+2;j<len;j++)//剩下的都是除数
{
num5=num5*10+a[j]-'0';
}
sum=sum-(num3*num4)/num5;
if(sum>Max)
Max=sum;
}
printf("Case #%d: %lld\n",flag++,Max);
}
}