1005题
codeforces上某题的加强版,我也是弄了好久才ac的,代码比较暴力,m,length都不是很大 100*11000*10(可能写错了),1s内还是ac了。
其中字符串的左移问题,我是把s串加倍,变成s+s然后再对s+s进行一个for循环预处理,判定的时候注意长度小于和等于length_s,还注意起点。。。见代码。。。
/*2012-01-20 20:42:38 Accepted 1005 671 MS 1132 KB GNU C++*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 20000
char ch[maxn], temp[ maxn+maxn ];
struct Info{
int len,kind;
char c[200];
}node[200];
int ans[maxn];
int next[maxn][26];
int solve(char *s,char *t){
int i,j,ns,nt;
ns= strlen(s);
nt= strlen(t);
for(i=0;i<26;++i)
next[ns-1][i]= -1;
for(i=ns-2;i>=0;--i){
for(j=0;j<26;++j)
next[i][j]= next[i+1][j];
next[i][ s[i+1]-'a' ]= i+1;
}
int index;
if( s[0]==t[0] ) index= 0;
else index= next[0][t[0]-'a'];
i= index;
int n= (ns>>1);
while(index<= n && index!=-1 ){
i= index;
for(j=1;j<nt;++j){
int NEXT= next[i][ t[j]-'a' ];
if( NEXT!=-1 && (NEXT-index+1)<= n )
i= NEXT;
else break;
}
if( j>=nt ) return 1;
else index= next[index][t[0]-'a'];
}
return 0;
}
int main()
{
//freopen("1005.txt","r",stdin);
int T,m,i,j;
cin>>T;
while(T--){
scanf("%s",ch);
cin>>m;
for(i=1;i<=m;++i){
scanf("%d%s",&node[i].kind,node[i].c);
node[i].len= strlen( node[i].c );
}
for(i=1;i<=m;++i){
if( node[i].kind==1 )
strcat( ch, node[i].c );
}
//puts(ch);
int Q=0;
for(i=m;i>=1;--i){
if( node[i].kind==1 ){
int n= strlen( ch );
ch[ n-node[i].len ]= '\0';
}
else{
strcpy( temp, ch );
strcat( temp, ch );
ans[++Q]= solve( temp, node[i].c );
}
}
for(i=Q;i>0;--i)
if( ans[i]==0 ) puts("NO");
else puts("YES");
}
}
1010题
给定n(1<=n<=10^9),求3个实数,使得x+y+z= n,同时使 x* ( y+ z^2 )最大,如果邮多个测试示例,按字典序输出,保留3位小数。
昨晚我的做法是n>=3时, 我瞎蒙的y=0有最大值,然后 f (x)= x* ( (n-x)^2 ),求导之后发现x=n/3,于是写了代码,提交wa,今天问了浮云牛,它的代码思路和我的一样,而不同的是n>=2的时候用这个公式,而我写的是 n=2的时候输出1.000 0.000 1.000
xtu黑水浮云2012-01-21 15:17:59
if(n==1) printf("0.500 0.500 0.000\n");
else printf("%.3f 0.000 %.3f\n",(double)n/3.0,(double)n*2/3.0);
然后群里提出了一个不是求导的方式来理解:
y=0时, x+z =n,有 2*x + z + z = 2*n, 对于 x*(z^2) <==> 0.5*( 2*x * z * z ),3个数的和一定,仅当3个数都相等时乘积最大。
有2x=z, x= n/3(注意C语言里的除法)。
可是,达尔戈提出了另一个观点,应该分x=0,y=0,z=0,3个情况来写, 理由是 对x来说是一次函数,对y来说是一次函数,对z来说是二次函数,一次函数是没有最大值,只能取边界值。
后来又 hnu的晴天大神说了哥拉格朗日乘数法计算,小学了下,发现自己还是不会,请教达尔戈,居然回复不可以用,大致内容如下,看来我果断得看书去:
-
达尔
2012-01-21 21:48:10
- 木有极大值
-
轨迹
2012-01-21 21:48:55
- 好吧,我理论知识极度匮乏,出题人也忽略了 他说他用了 拉格朗日乘数法来做数据。
-
达尔
2012-01-21 21:49:25
- 是的。。。
-
达尔
2012-01-21 21:49:36
- 昨晚他们找我就是说这个
-
轨迹
2012-01-21 21:50:58
- 最后一个问题,你怎么知道它木有极大值
-
达尔
2012-01-21 21:53:10
- 还是下午那个说话。。。你见过一次函数有极大值么
-
轨迹
2012-01-21 21:53:31
- 可是 z是二次的 你自己说的。
-
轨迹
2012-01-21 21:54:05
- 一个函数的阶次应该是由有次数最高的那个来决定的不是吗
-
达尔
2012-01-21 21:55:27
- 拉格朗日乘子法,需要用二次偏导验算,而对x和y的二次偏导都是等于0
-
达尔
2012-01-21 21:55:36
- 这是最理论的说法了