F. UVALive 6439 Pasti Pas!
字符串问题,题意就是让你通过合并一些连续的字符串为其它的字符从而使它成为一个回文串,并且回文串的长度要最长。
思路:一边从字符串前段开始,一边从后段开始,判断,如果两个字符串不相等,就接着添加下一个字符进来,直至两个字符串相等位置,此时ans+=2,到字符串中间处停止(因为字符串本身有规律,所以没有必要判断到最后一个,而是到中间处就行了,减少了时间),其中有些细节要注意。比赛的时候由于方法不够灵活,T了好多次啊。
代码参考baoge的如下:
#include<algorithm>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define maxn 50010
using namespace std;
string str1,str2,str3;
int main()
{
int n,ans;
cin>>n;
for(int i=1; i<=n; i++)
{
ans=0;
str2="";
str3="";
cin>>str1;
int len=str1.length();
for(int j=0; j<(len>>1); j++)
{
str2=str2+str1[j];
str3=str1[len-j-1]+str3;
if(str2==str3)
{
ans+=2;
str2=str3="";
}
}
if(str2!=""&&len%2==0) ans++;
if(len%2) ans++;
printf("Case #%d: %d\n",i,ans);
}
return 0;
}
这道题如果按照上面这种处理方法,要是数据量大的话,可能会T,所以最保险的方法还是用哈希法来做。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#define ull unsigned long long
#define maxn 50010
#define x 33
using namespace std;
char str[maxn];
ull m[maxn];
int main()
{
int t;
m[0]=1;
for(int i=1; i<=50001; i++)
m[i]=m[i-1]*x;
cin>>t;
for(int i=1; i<=t; i++)
{
scanf("%s",str);
ull head=0;
ull tail=0;
int ans=0;
int from=0;
int len=strlen(str);
for(int j=0; j<len>>1; j++)
{
head*=x;
head+=(int)(str[j]-'A'+1);
tail+=m[j-from]*(int)(str[len-1-j]-'A'+1);
if(head==tail)
{
ans+=2;
from=j+1;
head=tail=0;
}
}
if(head!=0&&len%2==0) ans++;
if(len%2==1) ans++;
printf("Case #%d: %d\n",i,ans);
}
return 0;
}
A. Number Assignment
解法:若要分割成n份,就相当于把(n-1)个相差最大的数隔开,前提是先排好顺序。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int T;
int main()
{
cin>>T;
for(int i=1;i<=T;i++)
{
int m,n;
cin>>m>>n;
int a[105],b[105];
for(int j=0;j<m;j++)
cin>>a[j];
sort(a,a+m);
int sum=a[m-1]-a[0];
for(int j=1;j<m;j++)
b[j-1]=a[j]-a[j-1];
sort(b,b+m-1,cmp);
for(int k=0;k<n-1;k++)
sum-=b[k];
cout<<"Case #"<<i<<": "<<sum<<endl;
}
return 0;
}